From 190ecd4e4e9749fce3834118a4757c9737aaaf2c Mon Sep 17 00:00:00 2001 From: Ewout Stortenbeker Date: Tue, 7 Jul 2020 13:42:44 +0200 Subject: [PATCH] new browser build with core dependency updates --- dist/browser.js | 24 ++++++++++++++++++------ dist/browser.min.js | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/dist/browser.js b/dist/browser.js index f903640..a86e29a 100644 --- a/dist/browser.js +++ b/dist/browser.js @@ -555,14 +555,16 @@ class DataReference { } /** - * Sets the value a node using a transaction: it runs you callback function with the current value, uses its return value as the new value to store. - * @param {(currentValue: DataSnapshot) => void} callback - callback function(currentValue) => newValue: is called with a snapshot of the current value, must return a new value to store in the database + * Sets the value a node using a transaction: it runs your callback function with the current value, uses its return value as the new value to store. + * The transaction is canceled if your callback returns undefined, or throws an error. If your callback returns null, the target node will be removed. + * @param {(currentValue: DataSnapshot) => any} callback - callback function that performs the transaction on the node's current value. It must return the new value to store (or promise with new value), undefined to cancel the transaction, or null to remove the node. * @returns {Promise} returns a promise that resolves with the DataReference once the transaction has been processed */ transaction(callback) { if (this.isWildcardPath) { throw new Error(`Cannot start a transaction on a path with wildcards and/or variables`); - } + } + let throwError; let cb = (currentValue) => { currentValue = this.db.types.deserialize(this.path, currentValue); const snap = new DataSnapshot(this, currentValue); @@ -571,12 +573,18 @@ class DataReference { newValue = callback(snap); } catch(err) { - // Make sure an exception thrown in client code cancels the transaction - return; + // callback code threw an error + throwError = err; // Remember error + return; // cancel transaction by returning undefined } if (newValue instanceof Promise) { - return newValue.then((val) => { + return newValue + .then((val) => { return this.db.types.serialize(this.path, val); + }) + .catch(err => { + throwError = err; // Remember error + return; // cancel transaction by returning undefined }); } else { @@ -585,6 +593,10 @@ class DataReference { } return this.db.api.transaction(this.path, cb) .then(result => { + if (throwError) { + // Rethrow error from callback code + throw throwError; + } return this; }); } diff --git a/dist/browser.min.js b/dist/browser.min.js index 7944962..256a44c 100644 --- a/dist/browser.min.js +++ b/dist/browser.min.js @@ -1 +1 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.acebase=f()}})((function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,(function(r){var n=e[i][1][r];return o(n||r)}),p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i=7&&stringLength<=10)return true;return false};cuid.fingerprint=fingerprint;module.exports=cuid},{"./lib/fingerprint.js":2,"./lib/pad.js":3}],2:[function(require,module,exports){var pad=require("./pad.js");var env=typeof window==="object"?window:self;var globalCount=Object.keys(env).length;var mimeTypesLength=navigator.mimeTypes?navigator.mimeTypes.length:0;var clientId=pad((mimeTypesLength+navigator.userAgent.length).toString(36)+globalCount.toString(36),4);module.exports=function fingerprint(){return clientId}},{"./pad.js":3}],3:[function(require,module,exports){module.exports=function pad(num,size){var s="000000000"+num;return s.substr(s.length-size)}},{}],4:[function(require,module,exports){const{EventEmitter:EventEmitter}=require("events");const{DataReference:DataReference,DataReferenceQuery:DataReferenceQuery}=require("./data-reference");const{TypeMappings:TypeMappings}=require("./type-mappings");class AceBaseSettings{constructor(options){this.logLevel=options.logLevel||"log"}}class AceBaseBase extends EventEmitter{constructor(dbname,options){super();if(!options){options={}}this.once("ready",()=>{this._ready=true});this.types=new TypeMappings(this)}ready(callback=undefined){if(this._ready===true){callback&&callback();return Promise.resolve()}else{let resolve;const promise=new Promise(res=>resolve=res);this.on("ready",()=>{resolve();callback&&callback()});return promise}}get isReady(){return this._ready===true}ref(path){return new DataReference(this,path)}get root(){return this.ref("")}query(path){const ref=new DataReference(this,path);return new DataReferenceQuery(ref)}get indexes(){return{get:()=>{return this.api.getIndexes()},create:(path,key,options)=>{return this.api.createIndex(path,key,options)}}}}module.exports={AceBaseBase:AceBaseBase,AceBaseSettings:AceBaseSettings}},{"./data-reference":7,"./type-mappings":16,events:41}],5:[function(require,module,exports){class Api{stats(options=undefined){}subscribe(path,event,callback){}unsubscribe(path,event,callback){}update(path,updates){}set(path,value){}get(path,options){}exists(path){}query(path,query,options){}createIndex(path,key){}getIndexes(){}}module.exports={Api:Api}},{}],6:[function(require,module,exports){const c=function(input,length,result){var i,j,n,b=[0,0,0,0,0];for(i=0;i";return ret},decode:function(input){if(!input.startsWith("<~")||!input.endsWith("~>")){throw new Error("Invalid input string")}input=input.substr(2,input.length-4);var n=input.length,r=[],b=[0,0,0,0,0],i,j,t,x,y,d;for(i=0;i>>=8;y=t&255;t>>>=8;r.push(t>>>8,t&255,y,x);for(j=d;j<5;++j,r.pop());i+=4}const data=new Uint8Array(r);return data.buffer.slice(data.byteOffset,data.byteOffset+data.byteLength)}};module.exports=ascii85},{}],7:[function(require,module,exports){const{DataSnapshot:DataSnapshot}=require("./data-snapshot");const{EventStream:EventStream,EventPublisher:EventPublisher}=require("./subscription");const{ID:ID}=require("./id");const debug=require("./debug");const{PathInfo:PathInfo}=require("./path-info");class DataRetrievalOptions{constructor(options){if(!options){options={}}if(typeof options.include!=="undefined"&&!(options.include instanceof Array)){throw new TypeError(`options.include must be an array`)}if(typeof options.exclude!=="undefined"&&!(options.exclude instanceof Array)){throw new TypeError(`options.exclude must be an array`)}if(typeof options.child_objects!=="undefined"&&typeof options.child_objects!=="boolean"){throw new TypeError(`options.child_objects must be a boolean`)}if(typeof options.allow_cache!=="undefined"&&typeof options.allow_cache!=="boolean"){throw new TypeError(`options.allow_cache must be a boolean`)}this.include=options.include||undefined;this.exclude=options.exclude||undefined;this.child_objects=typeof options.child_objects==="boolean"?options.child_objects:undefined;this.allow_cache=typeof options.allow_cache==="boolean"?options.allow_cache:undefined}}class QueryDataRetrievalOptions extends DataRetrievalOptions{constructor(options){super(options);if(typeof options.snapshots!=="undefined"&&typeof options.snapshots!=="boolean"){throw new TypeError(`options.snapshots must be an array`)}this.snapshots=typeof options.snapshots==="boolean"?options.snapshots:undefined}}const _private=Symbol("private");class DataReference{constructor(db,path,vars){if(!path){path=""}path=path.replace(/^\/|\/$/g,"");const pathInfo=PathInfo.get(path);const key=pathInfo.key;const callbacks=[];this[_private]={get path(){return path},get key(){return key},get callbacks(){return callbacks},vars:vars||{}};this.db=db}get path(){return this[_private].path}get key(){return this[_private].key}get parent(){let currentPath=PathInfo.fillVariables2(this.path,this.vars);const info=PathInfo.get(currentPath);if(info.parentPath===null){return null}return new DataReference(this.db,info.parentPath)}get vars(){return this[_private].vars}child(childPath){childPath=typeof childPath==="number"?childPath:childPath.replace(/^\/|\/$/g,"");const currentPath=PathInfo.fillVariables2(this.path,this.vars);const targetPath=PathInfo.getChildPath(currentPath,childPath);return new DataReference(this.db,targetPath)}set(value,onComplete=undefined){if(this.isWildcardPath){throw new Error(`Cannot set the value of a path with wildcards and/or variables`)}if(this.parent===null){throw new Error(`Cannot set the root object. Use update, or set individual child properties`)}if(typeof value==="undefined"){throw new TypeError(`Cannot store value undefined`)}value=this.db.types.serialize(this.path,value);return this.db.api.set(this.path,value).then(res=>{if(typeof onComplete==="function"){try{onComplete(null,this)}catch(err){console.error(`Error in onComplete callback:`,err)}}}).catch(err=>{if(typeof onComplete==="function"){try{onComplete(err)}catch(err){console.error(`Error in onComplete callback:`,err)}}else{throw err}}).then(()=>{return this})}update(updates,onComplete=undefined){if(this.isWildcardPath){throw new Error(`Cannot update the value of a path with wildcards and/or variables`)}let promise;if(typeof updates!=="object"||updates instanceof Array||updates instanceof ArrayBuffer||updates instanceof Date){promise=this.set(updates)}else if(Object.keys(updates).length===0){console.warn(`update called on path "/${this.path}", but there is nothing to update`);return Promise.resolve()}else{updates=this.db.types.serialize(this.path,updates);promise=this.db.api.update(this.path,updates)}return promise.then(()=>{if(typeof onComplete==="function"){try{onComplete(null,this)}catch(err){console.error(`Error in onComplete callback:`,err)}}}).catch(err=>{if(typeof onComplete==="function"){try{onComplete(err)}catch(err){console.error(`Error in onComplete callback:`,err)}}else{throw err}}).then(()=>{return this})}transaction(callback){if(this.isWildcardPath){throw new Error(`Cannot start a transaction on a path with wildcards and/or variables`)}let cb=currentValue=>{currentValue=this.db.types.deserialize(this.path,currentValue);const snap=new DataSnapshot(this,currentValue);let newValue;try{newValue=callback(snap)}catch(err){return}if(newValue instanceof Promise){return newValue.then(val=>{return this.db.types.serialize(this.path,val)})}else{return this.db.types.serialize(this.path,newValue)}};return this.db.api.transaction(this.path,cb).then(result=>{return this})}on(event,callback,cancelCallbackOrContext,context){if(this.path===""&&["value","notify_value","child_changed","notify_child_changed"].includes(event)){console.warn(`WARNING: Listening for value and child_changed events on the root node is a bad practice`)}const cancelCallback=typeof cancelCallbackOrContext==="function"&&cancelCallbackOrContext;context=typeof cancelCallbackOrContext==="object"?cancelCallbackOrContext:context;const useCallback=typeof callback==="function";let eventPublisher=null;const eventStream=new EventStream(publisher=>{eventPublisher=publisher});let cb={subscr:eventStream,original:callback,ours:(err,path,newValue,oldValue)=>{if(err){debug.error(`Error getting data for event ${event} on path "${path}"`,err);return}let ref=this.db.ref(path);ref[_private].vars=PathInfo.extractVariables(this.path,path);let callbackObject;if(event.startsWith("notify_")){callbackObject=ref}else{const isRemoved=event==="child_removed";const val=this.db.types.deserialize(path,isRemoved?oldValue:newValue);const snap=new DataSnapshot(ref,val,isRemoved);callbackObject=snap}try{useCallback&&callback.call(context||null,callbackObject)}catch(err){console.error(`ERROR firing "${event}" callback for path "${path}":`,err)}let keep=eventPublisher.publish(callbackObject);if(!keep&&!useCallback){let callbacks=this[_private].callbacks;callbacks.splice(callbacks.indexOf(cb),1);this.db.api.unsubscribe(this.path,event,cb.ours)}}};this[_private].callbacks.push(cb);let authorized=this.db.api.subscribe(this.path,event,cb.ours);const allSubscriptionsStoppedCallback=()=>{let callbacks=this[_private].callbacks;callbacks.splice(callbacks.indexOf(cb),1);this.db.api.unsubscribe(this.path,event,cb.ours)};if(authorized instanceof Promise){authorized.then(()=>{eventPublisher.start(allSubscriptionsStoppedCallback)}).catch(err=>{let callbacks=this[_private].callbacks;callbacks.splice(callbacks.indexOf(cb),1);this.db.api.unsubscribe(this.path,event,cb.ours);eventPublisher.cancel(err.message);cancelCallback&&cancelCallback(err.message)})}else{eventPublisher.start(allSubscriptionsStoppedCallback)}if(callback&&!this.isWildcardPath){if(event==="value"){this.get(snap=>{eventPublisher.publish(snap);useCallback&&callback(snap)})}else if(event==="child_added"){this.get(snap=>{const val=snap.val();if(val===null||typeof val!=="object"){return}Object.keys(val).forEach(key=>{let childSnap=new DataSnapshot(this.child(key),val[key]);eventPublisher.publish(childSnap);useCallback&&callback(childSnap)})})}else if(event==="notify_child_added"){const step=100;let limit=step,skip=0;const more=()=>{this.db.api.reflect(this.path,"children",{limit:limit,skip:skip}).then(children=>{children.list.forEach(child=>{const childRef=this.child(child.key);eventPublisher.publish(childRef);useCallback&&callback(childRef)});if(children.more){skip+=step;more()}})};more()}}return eventStream}off(event=undefined,callback=undefined){const callbacks=this[_private].callbacks;if(callback){const cb=callbacks.find(cb=>cb.original===callback);if(!cb){debug.error(`Can't find specified callback to unsubscribe from (path: "${this.path}", event: ${event}, callback: ${callback})`);return}callbacks.splice(callbacks.indexOf(cb),1);callback=cb.ours;cb.subscr.unsubscribe(callback)}else{callbacks.splice(0,callbacks.length).forEach(cb=>{cb.subscr.unsubscribe()})}this.db.api.unsubscribe(this.path,event,callback);return this}get(optionsOrCallback=undefined,callback=undefined){if(this.isWildcardPath){throw new Error(`Cannot get the value of a path with wildcards and/or variables. Use .query() instead`)}callback=typeof optionsOrCallback==="function"?optionsOrCallback:typeof callback==="function"?callback:undefined;const options=typeof optionsOrCallback==="object"?optionsOrCallback:new DataRetrievalOptions({allow_cache:true});if(typeof options.allow_cache==="undefined"){options.allow_cache=true}const promise=this.db.api.get(this.path,options).then(value=>{value=this.db.types.deserialize(this.path,value);const snapshot=new DataSnapshot(this,value);return snapshot});if(callback){promise.then(callback);return}else{return promise}}once(event,options){if(event==="value"&&!this.isWildcardPath){return this.get(options)}return new Promise((resolve,reject)=>{const callback=snap=>{this.off(event,snap);resolve(snap)};this.on(event,callback)})}push(value=undefined,onComplete=undefined){if(this.isWildcardPath){throw new Error(`Cannot push to a path with wildcards and/or variables`)}const id=ID.generate();const ref=this.child(id);ref.__pushed=true;if(typeof value!=="undefined"){return ref.set(value,onComplete).then(res=>ref)}else{return ref}}remove(){if(this.isWildcardPath){throw new Error(`Cannot remove a path with wildcards and/or variables. Use query().remove instead`)}if(this.parent===null){throw new Error(`Cannot remove the top node`)}return this.set(null)}exists(){if(this.isWildcardPath){throw new Error(`Cannot push to a path with wildcards and/or variables`)}return this.db.api.exists(this.path)}get isWildcardPath(){return this.path.indexOf("*")>=0||this.path.indexOf("$")>=0}query(){return new DataReferenceQuery(this)}reflect(type,args){if(this.pathHasVariables){throw new Error(`Cannot reflect on a path with wildcards and/or variables`)}return this.db.api.reflect(this.path,type,args)}export(stream,options={format:"json"}){return this.db.api.export(this.path,stream,options)}}class DataReferenceQuery{constructor(ref){this.ref=ref;this[_private]={filters:[],skip:0,take:0,order:[]}}filter(key,op,compare){if((op==="in"||op==="!in")&&(!(compare instanceof Array)||compare.length===0)){throw new Error(`${op} filter for ${key} must supply an Array compare argument containing at least 1 value`)}if((op==="between"||op==="!between")&&(!(compare instanceof Array)||compare.length!==2)){throw new Error(`${op} filter for ${key} must supply an Array compare argument containing 2 values`)}if((op==="matches"||op==="!matches")&&!(compare instanceof RegExp)){throw new Error(`${op} filter for ${key} must supply a RegExp compare argument`)}if((op==="contains"||op==="!contains")&&(typeof compare==="object"&&!(compare instanceof Array)&&!(compare instanceof Date)||compare instanceof Array&&compare.length===0)){throw new Error(`${op} filter for ${key} must supply a simple value or (non-zero length) array compare argument`)}this[_private].filters.push({key:key,op:op,compare:compare});return this}where(key,op,compare){return this.filter(key,op,compare)}take(n){this[_private].take=n;return this}skip(n){this[_private].skip=n;return this}sort(key,ascending=true){if(typeof key!=="string"){throw`key must be a string`}this[_private].order.push({key:key,ascending:ascending});return this}order(key,ascending=true){return this.sort(key,ascending)}get(optionsOrCallback=undefined,callback=undefined){callback=typeof optionsOrCallback==="function"?optionsOrCallback:typeof callback==="function"?callback:undefined;const options=typeof optionsOrCallback==="object"?optionsOrCallback:new QueryDataRetrievalOptions({snapshots:true,allow_cache:true});if(typeof options.snapshots==="undefined"){options.snapshots=true}if(typeof options.allow_cache==="undefined"){options.allow_cache=true}options.eventHandler=ev=>{if(!this._events||!this._events[ev.name]){return false}const listeners=this._events[ev.name];if(typeof listeners!=="object"||listeners.length===0){return false}if(["add","change","remove"].includes(ev.name)){const ref=new DataReference(this.ref.db,ev.path);const eventData={name:ev.name};if(options.snapshots&&ev.name!=="remove"){const val=db.types.deserialize(ev.path,ev.value);eventData.snapshot=new DataSnapshot(ref,val,false)}else{eventData.ref=ref}ev=eventData}listeners.forEach(callback=>{try{callback(ev)}catch(e){}})};options.monitor={add:false,change:false,remove:false};if(this._events){if(this._events["add"]&&this._events["add"].length>0){options.monitor.add=true}if(this._events["change"]&&this._events["change"].length>0){options.monitor.change=true}if(this._events["remove"]&&this._events["remove"].length>0){options.monitor.remove=true}}const db=this.ref.db;return db.api.query(this.ref.path,this[_private],options).catch(err=>{throw new Error(err)}).then(results=>{results.forEach((result,index)=>{if(options.snapshots){const val=db.types.deserialize(result.path,result.val);results[index]=new DataSnapshot(db.ref(result.path),val)}else{results[index]=db.ref(result)}});if(options.snapshots){return DataSnapshotsArray.from(results)}else{return DataReferencesArray.from(results)}}).then(results=>{callback&&callback(results);return results})}getRefs(callback=undefined){return this.get({snapshots:false},callback)}remove(callback){return this.get({snapshots:false}).then(refs=>{const promises=[];return Promise.all(refs.map(ref=>ref.remove())).then(()=>{callback&&callback()})})}on(event,callback){if(!this._events){this._events={}}if(!this._events[event]){this._events[event]=[]}this._events[event].push(callback);return this}off(event,callback){if(!this._events){return this}if(typeof event==="undefined"){this._events={};return this}if(!this._events[event]){return this}if(typeof callback==="undefined"){delete this._events[event];return this}const index=!this._events[event].indexOf(callback);if(!~index){return this}this._events[event].splice(index,1);return this}}class DataSnapshotsArray extends Array{static from(snaps){const arr=new DataSnapshotsArray(snaps.length);snaps.forEach((snap,i)=>arr[i]=snap);return arr}getValues(){return this.map(snap=>snap.val())}}class DataReferencesArray extends Array{static from(refs){const arr=new DataReferencesArray(refs.length);refs.forEach((ref,i)=>arr[i]=ref);return arr}getPaths(){return this.map(ref=>ref.path)}}module.exports={DataReference:DataReference,DataReferenceQuery:DataReferenceQuery,DataRetrievalOptions:DataRetrievalOptions,QueryDataRetrievalOptions:QueryDataRetrievalOptions}},{"./data-snapshot":8,"./debug":9,"./id":10,"./path-info":12,"./subscription":14}],8:[function(require,module,exports){const{DataReference:DataReference}=require("./data-reference");const{getPathKeys:getPathKeys}=require("./path-info");const getChild=(snapshot,path)=>{if(!snapshot.exists()){return null}let child=snapshot.val();getPathKeys(path).every(key=>{child=child[key];return typeof child!=="undefined"});return child||null};const getChildren=snapshot=>{if(!snapshot.exists()){return[]}let value=snapshot.val();if(value instanceof Array){return new Array(value.length).map((v,i)=>i)}if(typeof value==="object"){return Object.keys(value)}return[]};class DataSnapshot{constructor(ref,value,isRemoved=false){this.ref=ref;this.val=()=>{return value};this.exists=()=>{if(isRemoved){return false}return value!==null&&typeof value!=="undefined"}}child(path){let child=getChild(this,path);return new DataSnapshot(this.ref.child(path),child)}hasChild(path){return getChild(this,path)!==null}hasChildren(){return getChildren(this).length>0}numChildren(){return getChildren(this).length}forEach(callback){const value=this.val();return getChildren(this).every((key,i)=>{const snap=new DataSnapshot(this.ref.child(key),value[key]);return callback(snap)})}get key(){return this.ref.key}}module.exports={DataSnapshot:DataSnapshot}},{"./data-reference":7,"./path-info":12}],9:[function(require,module,exports){class DebugLogger{constructor(level="log",prefix=""){this.prefix=prefix;this.setLevel(level)}setLevel(level){const prefix=this.prefix?this.prefix:"";this.level=level;this.verbose=["verbose"].includes(level)?console.log.bind(console,prefix):()=>{};this.log=["verbose","log"].includes(level)?console.log.bind(console,prefix):()=>{};this.warn=["verbose","log","warn"].includes(level)?console.warn.bind(console,prefix):()=>{};this.error=["verbose","log","warn","error"].includes(level)?console.error.bind(console,prefix):()=>{};this.write=console.log.bind(console)}}module.exports=DebugLogger},{}],10:[function(require,module,exports){const cuid=require("cuid");class ID{static generate(){return cuid().slice(1)}}module.exports={ID:ID}},{cuid:1}],11:[function(require,module,exports){const{AceBaseBase:AceBaseBase,AceBaseSettings:AceBaseSettings}=require("./acebase-base");const{Api:Api}=require("./api");const{DataReference:DataReference,DataReferenceQuery:DataReferenceQuery,DataRetrievalOptions:DataRetrievalOptions,QueryDataRetrievalOptions:QueryDataRetrievalOptions}=require("./data-reference");const{DataSnapshot:DataSnapshot}=require("./data-snapshot");const DebugLogger=require("./debug");const{ID:ID}=require("./id");const{PathReference:PathReference}=require("./path-reference");const{EventStream:EventStream,EventPublisher:EventPublisher,EventSubscription:EventSubscription}=require("./subscription");const Transport=require("./transport");const{TypeMappings:TypeMappings,TypeMappingOptions:TypeMappingOptions}=require("./type-mappings");const Utils=require("./utils");const{PathInfo:PathInfo}=require("./path-info");const ascii85=require("./ascii85");module.exports={AceBaseBase:AceBaseBase,AceBaseSettings:AceBaseSettings,Api:Api,DataReference:DataReference,DataReferenceQuery:DataReferenceQuery,DataRetrievalOptions:DataRetrievalOptions,QueryDataRetrievalOptions:QueryDataRetrievalOptions,DataSnapshot:DataSnapshot,DebugLogger:DebugLogger,ID:ID,PathReference:PathReference,EventStream:EventStream,EventPublisher:EventPublisher,EventSubscription:EventSubscription,Transport:Transport,TypeMappings:TypeMappings,TypeMappingOptions:TypeMappingOptions,Utils:Utils,PathInfo:PathInfo,ascii85:ascii85}},{"./acebase-base":4,"./api":5,"./ascii85":6,"./data-reference":7,"./data-snapshot":8,"./debug":9,"./id":10,"./path-info":12,"./path-reference":13,"./subscription":14,"./transport":15,"./type-mappings":16,"./utils":17}],12:[function(require,module,exports){function getPathKeys(path){if(path.length===0){return[]}let keys=path.replace(/\[/g,"/[").split("/");keys.forEach((key,index)=>{if(key.startsWith("[")){keys[index]=parseInt(key.substr(1,key.length-2))}});return keys}function getPathInfo(path){if(path.length===0){return{parent:null,key:""}}const i=Math.max(path.lastIndexOf("/"),path.lastIndexOf("["));const parentPath=i<0?"":path.substr(0,i);let key=i<0?path:path.substr(i);if(key.startsWith("[")){key=parseInt(key.substr(1,key.length-2))}else if(key.startsWith("/")){key=key.substr(1)}if(parentPath===path){parentPath=null}return{parent:parentPath,key:key}}function getChildPath(path,key){if(path.length===0){if(typeof key==="number"){throw new TypeError("Cannot add array index to root path!")}return key}if(typeof key==="number"){return`${path}[${key}]`}return`${path}/${key}`}class PathInfo{static get(path){return new PathInfo(path)}static getChildPath(path,childKey){return getChildPath(path,childKey)}static getPathKeys(path){return getPathKeys(path)}constructor(path){this.path=path}get key(){return getPathInfo(this.path).key}get parentPath(){return getPathInfo(this.path).parent}childPath(childKey){return getChildPath(`${this.path}`,childKey)}get pathKeys(){return getPathKeys(this.path)}static extractVariables(varPath,fullPath){if(!varPath.includes("*")&&!varPath.includes("$")){return[]}const keys=getPathKeys(varPath);const pathKeys=getPathKeys(fullPath);let count=0;const variables={get length(){return count}};keys.forEach((key,index)=>{const pathKey=pathKeys[index];if(key==="*"){variables[count++]=pathKey}else if(typeof key==="string"&&key[0]==="$"){variables[count++]=pathKey;variables[key]=pathKey;const varName=key.slice(1);if(typeof variables[varName]==="undefined"){variables[varName]=pathKey}}});return variables}static fillVariables(varPath,fullPath){if(varPath.indexOf("*")<0&&varPath.indexOf("$")<0){return varPath}const keys=getPathKeys(varPath);const pathKeys=getPathKeys(fullPath);let merged=keys.map((key,index)=>{if(key===pathKeys[index]||index>=pathKeys.length){return key}else if(typeof key==="string"&&(key==="*"||key[0]==="$")){return pathKeys[index]}else{throw new Error(`Path "${fullPath}" cannot be used to fill variables of path "${this.path}" because they do not match`)}});let mergedPath="";merged.forEach(key=>{if(typeof key==="number"){mergedPath+=`[${key}]`}else{if(mergedPath.length>0){mergedPath+="/"}mergedPath+=key}});return mergedPath}static fillVariables2(varPath,vars){if(typeof vars!=="object"||Object.keys(vars).length===0){return varPath}let pathKeys=getPathKeys(varPath);let n=0;const targetPath=pathKeys.reduce((path,key)=>{if(key==="*"||key.startsWith("$")){key=vars[n++]}if(typeof key==="number"){return`${path}[${key}]`}else{return`${path}/${key}`}},"");return targetPath}equals(otherPath){if(this.path===otherPath){return true}const keys=getPathKeys(this.path);const otherKeys=getPathKeys(otherPath);if(keys.length!==otherKeys.length){return false}return keys.every((key,index)=>{const otherKey=otherKeys[index];return otherKey===key||typeof otherKey==="string"&&(otherKey==="*"||otherKey[0]==="$")||typeof key==="string"&&(key==="*"||key[0]==="$")})}isAncestorOf(descendantPath){if(descendantPath===""||this.path===descendantPath){return false}if(this.path===""){return true}const ancestorKeys=getPathKeys(this.path);const descendantKeys=getPathKeys(descendantPath);if(ancestorKeys.length>=descendantKeys.length){return false}return ancestorKeys.every((key,index)=>{const otherKey=descendantKeys[index];return otherKey===key||typeof otherKey==="string"&&(otherKey==="*"||otherKey[0]==="$")||typeof key==="string"&&(key==="*"||key[0]==="$")})}isDescendantOf(ancestorPath){if(this.path===""||this.path===ancestorPath){return false}if(ancestorPath===""){return true}const ancestorKeys=getPathKeys(ancestorPath);const descendantKeys=getPathKeys(this.path);if(ancestorKeys.length>=descendantKeys.length){return false}return ancestorKeys.every((key,index)=>{const otherKey=descendantKeys[index];return otherKey===key||typeof otherKey==="string"&&(otherKey==="*"||otherKey[0]==="$")||typeof key==="string"&&(key==="*"||key[0]==="$")})}isChildOf(otherPath){if(this.path===""){return false}const parentInfo=PathInfo.get(this.parentPath);return parentInfo.equals(otherPath)}isParentOf(otherPath){if(otherPath===""){return false}const parentInfo=PathInfo.get(PathInfo.get(otherPath).parentPath);return parentInfo.equals(this.path)}}module.exports={getPathInfo:getPathInfo,getChildPath:getChildPath,getPathKeys:getPathKeys,PathInfo:PathInfo}},{}],13:[function(require,module,exports){class PathReference{constructor(path){this.path=path}}module.exports={PathReference:PathReference}},{}],14:[function(require,module,exports){class EventSubscription{constructor(stop){this.stop=stop;this._internal={state:"init",cancelReason:undefined,activatePromises:[]}}activated(callback=undefined){if(callback){this._internal.activatePromises.push({callback:callback});if(this._internal.state==="active"){callback(true)}else if(this._internal.state==="canceled"){callback(false,this._internal.cancelReason)}}return new Promise((resolve,reject)=>{if(this._internal.state==="active"){return resolve()}else if(this._internal.state==="canceled"&&!callback){return reject(new Error(this._internal.cancelReason))}this._internal.activatePromises.push({resolve:resolve,reject:callback?()=>{}:reject})})}_setActivationState(activated,cancelReason){this._internal.cancelReason=cancelReason;this._internal.state=activated?"active":"canceled";while(this._internal.activatePromises.length>0){const p=this._internal.activatePromises.shift();if(activated){p.callback&&p.callback(true);p.resolve&&p.resolve()}else{p.callback&&p.callback(false,cancelReason);p.reject&&p.reject(cancelReason)}}}}class EventPublisher{constructor(publish,start,cancel){this.publish=publish;this.start=start;this.cancel=cancel}}class EventStream{constructor(eventPublisherCallback){const subscribers=[];let noMoreSubscribersCallback;let activationState;const _stoppedState="stopped (no more subscribers)";this.subscribe=(callback,activationCallback)=>{if(typeof callback!=="function"){throw new TypeError("callback must be a function")}else if(activationState===_stoppedState){throw new Error("stream can't be used anymore because all subscribers were stopped")}const sub={callback:callback,activationCallback:function(activated,cancelReason){activationCallback&&activationCallback(activated,cancelReason);this.subscription._setActivationState(activated,cancelReason)},subscription:new EventSubscription((function stop(){subscribers.splice(subscribers.indexOf(this),1);checkActiveSubscribers()}))};subscribers.push(sub);if(typeof activationState!=="undefined"){if(activationState===true){activationCallback&&activationCallback(true);sub.subscription._setActivationState(true)}else if(typeof activationState==="string"){activationCallback&&activationCallback(false,activationState);sub.subscription._setActivationState(false,activationState)}}return sub.subscription};const checkActiveSubscribers=()=>{if(subscribers.length===0){noMoreSubscribersCallback&&noMoreSubscribersCallback();activationState=_stoppedState}};this.unsubscribe=(callback=undefined)=>{const remove=callback?subscribers.filter(sub=>sub.callback===callback):subscribers;remove.forEach(sub=>{const i=subscribers.indexOf(sub);subscribers.splice(i,1)});checkActiveSubscribers()};this.stop=()=>{subscribers.splice(0);checkActiveSubscribers()};const publish=val=>{subscribers.forEach(sub=>{try{sub.callback(val)}catch(err){debug.error(`Error running subscriber callback: ${err.message}`)}});return subscribers.length>0};const start=allSubscriptionsStoppedCallback=>{activationState=true;noMoreSubscribersCallback=allSubscriptionsStoppedCallback;subscribers.forEach(sub=>{sub.activationCallback&&sub.activationCallback(true)})};const cancel=reason=>{activationState=reason;subscribers.forEach(sub=>{sub.activationCallback&&sub.activationCallback(false,reason||new Error("unknown reason"))});subscribers.splice()};const publisher=new EventPublisher(publish,start,cancel);eventPublisherCallback(publisher)}}module.exports={EventStream:EventStream,EventPublisher:EventPublisher,EventSubscription:EventSubscription}},{}],15:[function(require,module,exports){const{PathReference:PathReference}=require("./path-reference");const{cloneObject:cloneObject}=require("./utils");const ascii85=require("./ascii85");module.exports={deserialize(data){if(data.map===null||typeof data.map==="undefined"){return data.val}const deserializeValue=(type,val)=>{if(type==="date"){return new Date(val)}else if(type==="binary"){return ascii85.decode(val)}else if(type==="reference"){return new PathReference(val)}else if(type==="regexp"){return new RegExp(val.pattern,val.flags)}return val};if(typeof data.map==="string"){return deserializeValue(data.map,data.val)}Object.keys(data.map).forEach(path=>{const type=data.map[path];const keys=path.replace(/\[/g,"/[").split("/");keys.forEach((key,index)=>{if(key.startsWith("[")){keys[index]=parseInt(key.substr(1,key.length-2))}});let parent=data;let key="val";let val=data.val;keys.forEach(k=>{key=k;parent=val;val=val[key]});parent[key]=deserializeValue(type,val)});return data.val},serialize(obj){if(obj===null||typeof obj!=="object"||obj instanceof Date||obj instanceof ArrayBuffer||obj instanceof PathReference){const ser=this.serialize({value:obj});return{map:ser.map.value,val:ser.val.value}}obj=cloneObject(obj);const process=(obj,mappings,prefix)=>{Object.keys(obj).forEach(key=>{const val=obj[key];const path=prefix.length===0?key:`${prefix}/${key}`;if(val instanceof Date){obj[key]=val.toISOString();mappings[path]="date"}else if(val instanceof ArrayBuffer){obj[key]=ascii85.encode(val);mappings[path]="binary"}else if(val instanceof PathReference){obj[key]=val.path;mappings[path]="reference"}else if(val instanceof RegExp){obj[key]={pattern:val.source,flags:val.flags};mappings[path]="regexp"}else if(typeof val==="object"&&val!==null){process(val,mappings,path)}})};const mappings={};process(obj,mappings,"");return{map:mappings,val:obj}}}},{"./ascii85":6,"./path-reference":13,"./utils":17}],16:[function(require,module,exports){const{cloneObject:cloneObject}=require("./utils");const{PathInfo:PathInfo}=require("./path-info");const{AceBaseBase:AceBaseBase}=require("./acebase-base");const{DataReference:DataReference}=require("./data-reference");const{DataSnapshot:DataSnapshot}=require("./data-snapshot");const get=(mappings,path)=>{path=path.replace(/^\/|\/$/g,"");const keys=PathInfo.getPathKeys(path);const mappedPath=Object.keys(mappings).find(mpath=>{const mkeys=PathInfo.getPathKeys(mpath);if(mkeys.length!==keys.length){return false}return mkeys.every((mkey,index)=>{if(mkey==="*"||mkey[0]==="$"){return true}return mkey===keys[index]})});const mapping=mappings[mappedPath];return mapping};const map=(mappings,path)=>{const targetPath=PathInfo.get(path).parentPath;if(targetPath===null){return}return get(mappings,targetPath)};const mapDeep=(mappings,entryPath)=>{entryPath=entryPath.replace(/^\/|\/$/g,"");const pathInfo=PathInfo.get(entryPath);const startPath=pathInfo.parentPath;const keys=startPath?PathInfo.getPathKeys(startPath):[];const matches=Object.keys(mappings).reduce((m,mpath)=>{const mkeys=PathInfo.getPathKeys(mpath);if(mkeys.length{if(index>=keys.length){return false}else if(mkey==="*"||mkey[0]==="$"||mkey===keys[index]){return true}else{isMatch=false;return false}})}if(isMatch){const mapping=mappings[mpath];m.push({path:mpath,type:mapping})}return m},[]);return matches};const process=(db,mappings,path,obj,action)=>{if(obj===null||typeof obj!=="object"){return obj}const keys=PathInfo.getPathKeys(path);const m=mapDeep(mappings,path);const changes=[];m.sort((a,b)=>PathInfo.getPathKeys(a.path).length>PathInfo.getPathKeys(b.path).length?-1:1);m.forEach(mapping=>{const mkeys=PathInfo.getPathKeys(mapping.path);mkeys.push("*");const mTrailKeys=mkeys.slice(keys.length);if(mTrailKeys.length===0){const vars=PathInfo.extractVariables(mapping.path,path);const ref=new DataReference(db,path,vars);if(action==="serialize"){obj=mapping.type.serialize(obj,ref)}else if(action==="deserialize"){const snap=new DataSnapshot(ref,obj);obj=mapping.type.deserialize(snap)}return}const process=(parentPath,parent,keys)=>{if(obj===null||typeof obj!=="object"){return obj}const key=keys[0];let children=[];if(key==="*"||key[0]==="$"){if(parent instanceof Array){children=parent.map((val,index)=>({key:index,val:val}))}else{children=Object.keys(parent).map(k=>({key:k,val:parent[k]}))}}else{const child=parent[key];if(typeof child==="object"){children.push({key:key,val:child})}}children.forEach(child=>{const childPath=PathInfo.getChildPath(parentPath,child.key);const vars=PathInfo.extractVariables(mapping.path,childPath);const ref=new DataReference(db,childPath,vars);if(keys.length===1){if(action==="serialize"){changes.push({parent:parent,key:child.key,original:parent[child.key]});parent[child.key]=mapping.type.serialize(child.val,ref)}else if(action==="deserialize"){const snap=new DataSnapshot(ref,child.val);parent[child.key]=mapping.type.deserialize(snap)}}else{process(childPath,child.val,keys.slice(1))}})};process(path,obj,mTrailKeys)});if(action==="serialize"){obj=cloneObject(obj);if(changes.length>0){changes.forEach(change=>{change.parent[change.key]=change.original})}}return obj};class TypeMappingOptions{constructor(options){if(!options){options={}}this.serializer=options.serializer;this.creator=options.creator}}const _mappings=Symbol("mappings");class TypeMappings{constructor(db){this.db=db;this[_mappings]={}}get mappings(){return this[_mappings]}map(path){return map(this[_mappings],path)}bind(path,type,options={}){if(typeof path!=="string"){throw new TypeError("path must be a string")}if(typeof type!=="function"){throw new TypeError("constructor must be a function")}if(typeof options.serializer==="undefined"){}else if(typeof options.serializer==="string"){if(typeof type.prototype[options.serializer]==="function"){options.serializer=type.prototype[options.serializer]}else{throw new TypeError(`${type.name}.prototype.${options.serializer} is not a function, cannot use it as serializer`)}}else if(typeof options.serializer!=="function"){throw new TypeError(`serializer for class ${type.name} must be a function, or the name of a prototype method`)}if(typeof options.creator==="undefined"){if(typeof type.create==="function"){options.creator=type.create}}else if(typeof options.creator==="string"){if(typeof type[options.creator]==="function"){options.creator=type[options.creator]}else{throw new TypeError(`${type.name}.${options.creator} is not a function, cannot use it as creator`)}}else if(typeof options.creator!=="function"){throw new TypeError(`creator for class ${type.name} must be a function, or the name of a static method`)}path=path.replace(/^\/|\/$/g,"");this[_mappings][path]={db:this.db,type:type,creator:options.creator,serializer:options.serializer,deserialize(snap){let obj;if(this.creator){obj=this.creator.call(this.type,snap)}else{obj=new this.type(snap)}return obj},serialize(obj,ref){if(this.serializer){obj=this.serializer.call(obj,ref,obj)}else if(obj&&typeof obj.serialize==="function"){obj=obj.serialize(ref,obj)}return obj}}}serialize(path,obj){return process(this.db,this[_mappings],path,obj,"serialize")}deserialize(path,obj){return process(this.db,this[_mappings],path,obj,"deserialize")}}module.exports={TypeMappings:TypeMappings,TypeMappingOptions:TypeMappingOptions}},{"./acebase-base":4,"./data-reference":7,"./data-snapshot":8,"./path-info":12,"./utils":17}],17:[function(require,module,exports){(function(Buffer){const{PathReference:PathReference}=require("./path-reference");function numberToBytes(number){const bytes=new Uint8Array(8);const view=new DataView(bytes.buffer);view.setFloat64(0,number);return new Array(...bytes)}function bytesToNumber(bytes){if(bytes.length<8){throw new TypeError("must be 8 bytes")}const bin=new Uint8Array(bytes);const view=new DataView(bin.buffer);const nr=view.getFloat64(0);return nr}function encodeString(str){if(typeof TextEncoder!=="undefined"){const encoder=new TextEncoder;return encoder.encode(str)}else if(typeof Buffer==="function"){const buf=Buffer.from(str,"utf-8");return new Uint8Array(buf.buffer,buf.byteOffset,buf.byteLength)}else{let arr=[];for(let i=0;i128){if((code&55296)===55296){const nextCode=str.charCodeAt(i+1);if((nextCode&56320)!==56320){throw new Error("follow-up utf-16 character does not start with 0xDC00")}i++;const p1=code&1023;const p2=nextCode&1023;code=65536|p1<<10|p2}if(code<2048){const b1=192|code>>6&31;const b2=128|code&63;arr.push(b1,b2)}else if(code<65536){const b1=224|code>>12&15;const b2=128|code>>6&63;const b3=128|code&63;arr.push(b1,b2,b3)}else if(code<2097152){const b1=240|code>>18&7;const b2=128|code>>12&63;const b3=128|code>>6&63;const b4=128|code&63;arr.push(b1,b2,b3,b4)}else{throw new Error(`Cannot convert character ${str.charAt(i)} (code ${code}) to utf-8`)}}else{arr.push(code<128?code:63)}}return new Uint8Array(arr)}}function decodeString(buffer){if(typeof TextDecoder!=="undefined"){const decoder=new TextDecoder;if(buffer instanceof Uint8Array){return decoder.decode(buffer)}const buf=Uint8Array.from(buffer);return decoder.decode(buf)}else if(typeof Buffer==="function"){if(buffer instanceof Buffer){return buffer.toString("utf-8")}else if(buffer instanceof Array){const typedArray=Uint8Array.from(buffer);const buf=Buffer.from(typedArray.buffer,typedArray.byteOffset,typedArray.byteOffset+typedArray.byteLength);return buf.toString("utf-8")}else if("buffer"in buffer&&buffer["buffer"]instanceof ArrayBuffer){const buf=Buffer.from(buffer["buffer"],buffer.byteOffset,buffer.byteOffset+buffer.byteLength);return buf.toString("utf-8")}else{throw new Error(`Unsupported buffer argument`)}}else{if(!(buffer instanceof Uint8Array)&&"buffer"in buffer&&buffer["buffer"]instanceof ArrayBuffer){buffer=new Uint8Array(buffer["buffer"],buffer.byteOffset,buffer.byteLength)}if(buffer instanceof Buffer||buffer instanceof Array||buffer instanceof Uint8Array){let str="";for(let i=0;i128){if((code&240)===240){const b1=code,b2=buffer[i+1],b3=buffer[i+2],b4=buffer[i+3];code=(b1&7)<<18|(b2&63)<<12|(b3&63)<<6|b4&63;i+=3}else if((code&224)===224){const b1=code,b2=buffer[i+1],b3=buffer[i+2];code=(b1&15)<<12|(b2&63)<<6|b3&63;i+=2}else if((code&192)===192){const b1=code,b2=buffer[i+1];code=(b1&31)<<6|b2&63;i++}else{throw new Error(`invalid utf-8 data`)}}if(code>=65536){code^=65536;const p1=55296|code>>10;const p2=56320|code&1023;str+=String.fromCharCode(p1);str+=String.fromCharCode(p2)}else{str+=String.fromCharCode(code)}}return str}else{throw new Error(`Unsupported buffer argument`)}}}function concatTypedArrays(a,b){const c=new a.constructor(a.length+b.length);c.set(a);c.set(b,a.length);return c}function cloneObject(original,stack){const{DataSnapshot:DataSnapshot}=require("./data-snapshot");if(original instanceof DataSnapshot){throw new TypeError(`Object to clone is a DataSnapshot (path "${original.ref.path}")`)}const checkAndFixTypedArray=obj=>{if(obj!==null&&typeof obj==="object"&&typeof obj.constructor==="function"&&typeof obj.constructor.name==="string"&&["Buffer","Uint8Array","Int8Array","Uint16Array","Int16Array","Uint32Array","Int32Array","BigUint64Array","BigInt64Array"].includes(obj.constructor.name)){obj=obj.buffer.slice(obj.byteOffset,obj.byteOffset+obj.byteLength)}return obj};original=checkAndFixTypedArray(original);if(typeof original!=="object"||original===null||original instanceof Date||original instanceof ArrayBuffer||original instanceof PathReference||original instanceof RegExp){return original}const cloneValue=val=>{if(stack.indexOf(val)>=0){throw new ReferenceError(`object contains a circular reference`)}val=checkAndFixTypedArray(val);if(val===null||val instanceof Date||val instanceof ArrayBuffer||val instanceof PathReference||val instanceof RegExp){return val}else if(val instanceof Array){stack.push(val);val=val.map(item=>cloneValue(item));stack.pop();return val}else if(typeof val==="object"){stack.push(val);val=cloneObject(val,stack);stack.pop();return val}else{return val}};if(typeof stack==="undefined"){stack=[original]}const clone=original instanceof Array?[]:{};Object.keys(original).forEach(key=>{let val=original[key];if(typeof val==="function"){return}clone[key]=cloneValue(val)});return clone}function compareValues(oldVal,newVal){const voids=[undefined,null];if(oldVal===newVal){return"identical"}else if(voids.indexOf(oldVal)>=0&&voids.indexOf(newVal)<0){return"added"}else if(voids.indexOf(oldVal)<0&&voids.indexOf(newVal)>=0){return"removed"}else if(typeof oldVal!==typeof newVal){return"changed"}else if(typeof oldVal==="object"&&!(oldVal instanceof Date)){const isArray=oldVal instanceof Array;const oldKeys=isArray?Object.keys(oldVal).map(v=>parseInt(v)):Object.keys(oldVal);const newKeys=isArray?Object.keys(newVal).map(v=>parseInt(v)):Object.keys(newVal);const removedKeys=oldKeys.filter(key=>newKeys.indexOf(key)<0);const addedKeys=newKeys.filter(key=>oldKeys.indexOf(key)<0);const changedKeys=newKeys.reduce((changed,key)=>{if(oldKeys.indexOf(key)>=0){const val1=oldVal[key];const val2=newVal[key];const c=compareValues(val1,val2);if(c!=="identical"){changed.push({key:key,change:c})}}return changed},[]);if(addedKeys.length===0&&removedKeys.length===0&&changedKeys.length===0){return"identical"}else{return{added:addedKeys,removed:removedKeys,changed:changedKeys}}}else if(oldVal!==newVal){return"changed"}return"identical"}const getChildValues=(childKey,oldValue,newValue)=>{oldValue=oldValue===null?null:oldValue[childKey];if(typeof oldValue==="undefined"){oldValue=null}newValue=newValue===null?null:newValue[childKey];if(typeof newValue==="undefined"){newValue=null}return{oldValue:oldValue,newValue:newValue}};module.exports={numberToBytes:numberToBytes,bytesToNumber:bytesToNumber,concatTypedArrays:concatTypedArrays,cloneObject:cloneObject,compareValues:compareValues,getChildValues:getChildValues,encodeString:encodeString,decodeString:decodeString}}).call(this,require("buffer").Buffer)},{"./data-snapshot":8,"./path-reference":13,buffer:40}],18:[function(require,module,exports){var colors={};module["exports"]=colors;colors.themes={};var util=require("util");var ansiStyles=colors.styles=require("./styles");var defineProps=Object.defineProperties;var newLineRegex=new RegExp(/[\r\n]+/g);colors.supportsColor=require("./system/supports-colors").supportsColor;if(typeof colors.enabled==="undefined"){colors.enabled=colors.supportsColor()!==false}colors.enable=function(){colors.enabled=true};colors.disable=function(){colors.enabled=false};colors.stripColors=colors.strip=function(str){return(""+str).replace(/\x1B\[\d+m/g,"")};var stylize=colors.stylize=function stylize(str,style){if(!colors.enabled){return str+""}return ansiStyles[style].open+str+ansiStyles[style].close};var matchOperatorsRe=/[|\\{}()[\]^$+*?.]/g;var escapeStringRegexp=function(str){if(typeof str!=="string"){throw new TypeError("Expected a string")}return str.replace(matchOperatorsRe,"\\$&")};function build(_styles){var builder=function builder(){return applyStyle.apply(builder,arguments)};builder._styles=_styles;builder.__proto__=proto;return builder}var styles=function(){var ret={};ansiStyles.grey=ansiStyles.gray;Object.keys(ansiStyles).forEach((function(key){ansiStyles[key].closeRe=new RegExp(escapeStringRegexp(ansiStyles[key].close),"g");ret[key]={get:function(){return build(this._styles.concat(key))}}}));return ret}();var proto=defineProps((function colors(){}),styles);function applyStyle(){var args=Array.prototype.slice.call(arguments);var str=args.map((function(arg){if(arg!=undefined&&arg.constructor===String){return arg}else{return util.inspect(arg)}})).join(" ");if(!colors.enabled||!str){return str}var newLinesPresent=str.indexOf("\n")!=-1;var nestedStyles=this._styles;var i=nestedStyles.length;while(i--){var code=ansiStyles[nestedStyles[i]];str=code.open+str.replace(code.closeRe,code.open)+code.close;if(newLinesPresent){str=str.replace(newLineRegex,(function(match){return code.close+match+code.open}))}}return str}colors.setTheme=function(theme){if(typeof theme==="string"){console.log("colors.setTheme now only accepts an object, not a string. "+"If you are trying to set a theme from a file, it is now your (the "+"caller's) responsibility to require the file. The old syntax "+"looked like colors.setTheme(__dirname + "+"'/../themes/generic-logging.js'); The new syntax looks like "+"colors.setTheme(require(__dirname + "+"'/../themes/generic-logging.js'));");return}for(var style in theme){(function(style){colors[style]=function(str){if(typeof theme[style]==="object"){var out=str;for(var i in theme[style]){out=colors[theme[style][i]](out)}return out}return colors[theme[style]](str)}})(style)}};function init(){var ret={};Object.keys(styles).forEach((function(name){ret[name]={get:function(){return build([name])}}}));return ret}var sequencer=function sequencer(map,str){var exploded=str.split("");exploded=exploded.map(map);return exploded.join("")};colors.trap=require("./custom/trap");colors.zalgo=require("./custom/zalgo");colors.maps={};colors.maps.america=require("./maps/america")(colors);colors.maps.zebra=require("./maps/zebra")(colors);colors.maps.rainbow=require("./maps/rainbow")(colors);colors.maps.random=require("./maps/random")(colors);for(var map in colors.maps){(function(map){colors[map]=function(str){return sequencer(colors.maps[map],str)}})(map)}defineProps(colors,init())},{"./custom/trap":19,"./custom/zalgo":20,"./maps/america":23,"./maps/rainbow":24,"./maps/random":25,"./maps/zebra":26,"./styles":27,"./system/supports-colors":29,util:46}],19:[function(require,module,exports){module["exports"]=function runTheTrap(text,options){var result="";text=text||"Run the trap, drop the bass";text=text.split("");var trap={a:["@","Ą","Ⱥ","Ʌ","Δ","Λ","Д"],b:["ß","Ɓ","Ƀ","ɮ","β","฿"],c:["©","Ȼ","Ͼ"],d:["Ð","Ɗ","Ԁ","ԁ","Ԃ","ԃ"],e:["Ë","ĕ","Ǝ","ɘ","Σ","ξ","Ҽ","੬"],f:["Ӻ"],g:["ɢ"],h:["Ħ","ƕ","Ң","Һ","Ӈ","Ԋ"],i:["༏"],j:["Ĵ"],k:["ĸ","Ҡ","Ӄ","Ԟ"],l:["Ĺ"],m:["ʍ","Ӎ","ӎ","Ԡ","ԡ","൩"],n:["Ñ","ŋ","Ɲ","Ͷ","Π","Ҋ"],o:["Ø","õ","ø","Ǿ","ʘ","Ѻ","ם","۝","๏"],p:["Ƿ","Ҏ"],q:["্"],r:["®","Ʀ","Ȑ","Ɍ","ʀ","Я"],s:["§","Ϟ","ϟ","Ϩ"],t:["Ł","Ŧ","ͳ"],u:["Ʊ","Ս"],v:["ט"],w:["Ш","Ѡ","Ѽ","൰"],x:["Ҳ","Ӿ","Ӽ","ӽ"],y:["¥","Ұ","Ӌ"],z:["Ƶ","ɀ"]};text.forEach((function(c){c=c.toLowerCase();var chars=trap[c]||[" "];var rand=Math.floor(Math.random()*chars.length);if(typeof trap[c]!=="undefined"){result+=trap[c][rand]}else{result+=c}}));return result}},{}],20:[function(require,module,exports){module["exports"]=function zalgo(text,options){text=text||" he is here ";var soul={up:["̍","̎","̄","̅","̿","̑","̆","̐","͒","͗","͑","̇","̈","̊","͂","̓","̈","͊","͋","͌","̃","̂","̌","͐","̀","́","̋","̏","̒","̓","̔","̽","̉","ͣ","ͤ","ͥ","ͦ","ͧ","ͨ","ͩ","ͪ","ͫ","ͬ","ͭ","ͮ","ͯ","̾","͛","͆","̚"],down:["̖","̗","̘","̙","̜","̝","̞","̟","̠","̤","̥","̦","̩","̪","̫","̬","̭","̮","̯","̰","̱","̲","̳","̹","̺","̻","̼","ͅ","͇","͈","͉","͍","͎","͓","͔","͕","͖","͙","͚","̣"],mid:["̕","̛","̀","́","͘","̡","̢","̧","̨","̴","̵","̶","͜","͝","͞","͟","͠","͢","̸","̷","͡"," ҉"]};var all=[].concat(soul.up,soul.down,soul.mid);function randomNumber(range){var r=Math.floor(Math.random()*range);return r}function isChar(character){var bool=false;all.filter((function(i){bool=i===character}));return bool}function heComes(text,options){var result="";var counts;var l;options=options||{};options["up"]=typeof options["up"]!=="undefined"?options["up"]:true;options["mid"]=typeof options["mid"]!=="undefined"?options["mid"]:true;options["down"]=typeof options["down"]!=="undefined"?options["down"]:true;options["size"]=typeof options["size"]!=="undefined"?options["size"]:"maxi";text=text.split("");for(l in text){if(isChar(l)){continue}result=result+text[l];counts={up:0,down:0,mid:0};switch(options.size){case"mini":counts.up=randomNumber(8);counts.mid=randomNumber(2);counts.down=randomNumber(8);break;case"maxi":counts.up=randomNumber(16)+3;counts.mid=randomNumber(4)+1;counts.down=randomNumber(64)+3;break;default:counts.up=randomNumber(8)+1;counts.mid=randomNumber(6)/2;counts.down=randomNumber(8)+1;break}var arr=["up","mid","down"];for(var d in arr){var index=arr[d];for(var i=0;i<=counts[index];i++){if(options[index]){result=result+soul[index][randomNumber(soul[index].length)]}}}}return result}return heComes(text,options)}},{}],21:[function(require,module,exports){var colors=require("./colors");module["exports"]=function(){var addProperty=function(color,func){String.prototype.__defineGetter__(color,func)};addProperty("strip",(function(){return colors.strip(this)}));addProperty("stripColors",(function(){return colors.strip(this)}));addProperty("trap",(function(){return colors.trap(this)}));addProperty("zalgo",(function(){return colors.zalgo(this)}));addProperty("zebra",(function(){return colors.zebra(this)}));addProperty("rainbow",(function(){return colors.rainbow(this)}));addProperty("random",(function(){return colors.random(this)}));addProperty("america",(function(){return colors.america(this)}));var x=Object.keys(colors.styles);x.forEach((function(style){addProperty(style,(function(){return colors.stylize(this,style)}))}));function applyTheme(theme){var stringPrototypeBlacklist=["__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__","charAt","constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf","charCodeAt","indexOf","lastIndexOf","length","localeCompare","match","repeat","replace","search","slice","split","substring","toLocaleLowerCase","toLocaleUpperCase","toLowerCase","toUpperCase","trim","trimLeft","trimRight"];Object.keys(theme).forEach((function(prop){if(stringPrototypeBlacklist.indexOf(prop)!==-1){console.log("warn: ".red+("String.prototype"+prop).magenta+" is probably something you don't want to override. "+"Ignoring style name")}else{if(typeof theme[prop]==="string"){colors[prop]=colors[theme[prop]]}else{var tmp=colors[theme[prop][0]];for(var t=1;t=2,has16m:level>=3}}function supportsColor(stream){if(forceColor===false){return 0}if(hasFlag("color=16m")||hasFlag("color=full")||hasFlag("color=truecolor")){return 3}if(hasFlag("color=256")){return 2}if(stream&&!stream.isTTY&&forceColor!==true){return 0}var min=forceColor?1:0;if(process.platform==="win32"){var osRelease=os.release().split(".");if(Number(process.versions.node.split(".")[0])>=8&&Number(osRelease[0])>=10&&Number(osRelease[2])>=10586){return Number(osRelease[2])>=14931?3:2}return 1}if("CI"in env){if(["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI"].some((function(sign){return sign in env}))||env.CI_NAME==="codeship"){return 1}return min}if("TEAMCITY_VERSION"in env){return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION)?1:0}if("TERM_PROGRAM"in env){var version=parseInt((env.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(env.TERM_PROGRAM){case"iTerm.app":return version>=3?3:2;case"Hyper":return 3;case"Apple_Terminal":return 2}}if(/-256(color)?$/i.test(env.TERM)){return 2}if(/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)){return 1}if("COLORTERM"in env){return 1}if(env.TERM==="dumb"){return min}return min}function getSupportLevel(stream){var level=supportsColor(stream);return translateLevel(level)}module.exports={supportsColor:getSupportLevel,stdout:getSupportLevel(process.stdout),stderr:getSupportLevel(process.stderr)}}).call(this,require("_process"))},{"./has-flag.js":28,_process:44,os:43}],30:[function(require,module,exports){const{AceBase:AceBase,AceBaseLocalSettings:AceBaseLocalSettings}=require("./acebase-local");const{CustomStorageSettings:CustomStorageSettings,CustomStorageTransaction:CustomStorageTransaction,CustomStorageHelpers:CustomStorageHelpers,ICustomStorageNode:ICustomStorageNode,ICustomStorageNodeMetaData:ICustomStorageNodeMetaData}=require("./storage-custom");const deprecatedConstructorError=`Using AceBase constructor in the browser to use localStorage is deprecated!\nSwitch to:\nIndexedDB implementation (FASTER, MORE RELIABLE):\n let db = AceBase.WithIndexedDB(name, settings)\nOr, new LocalStorage implementation:\n let db = AceBase.WithLocalStorage(name, settings)\nOr, write your own CustomStorage adapter:\n let myCustomStorage = new CustomStorageSettings({ ... });\n let db = new AceBase(name, { storage: myCustomStorage })`;class BrowserAceBase extends AceBase{constructor(name,settings){if(typeof settings!=="object"||typeof settings.storage!=="object"){throw new Error(deprecatedConstructorError)}super(name,settings)}static WithIndexedDB(dbname,settings){settings=settings||{};if(!settings.logLevel){settings.logLevel="error"}const IndexedDB=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB;let request=IndexedDB.open(`${dbname}.acebase`,1);let readyResolve,readyReject,readyPromise=new Promise((rs,rj)=>{readyResolve=rs;readyReject=rj});request.onupgradeneeded=e=>{let db=request.result;db.createObjectStore("nodes",{keyPath:"path"});db.createObjectStore("content")};let db;request.onsuccess=e=>{db=request.result;readyResolve()};request.onerror=e=>{readyReject(e)};const storageSettings=new CustomStorageSettings({name:"IndexedDB",locking:true,ready(){return readyPromise},async getTransaction(target){await readyPromise;const context={debug:true,db:db};return new IndexedDBStorageTransaction(context,target)}});return new AceBase(dbname,{logLevel:settings.logLevel,storage:storageSettings})}}function _requestToPromise(request){return new Promise((resolve,reject)=>{request.onsuccess=event=>{return resolve(request.result||null)};request.onerror=reject})}class IndexedDBStorageTransaction extends CustomStorageTransaction{constructor(context,target){super(target);this.context=context;this._pending=[]}_createTransaction(write=false){const tx=this.context.db.transaction(["nodes","content"],write?"readwrite":"readonly");return tx}commit(){if(this._pending.length===0){return Promise.resolve()}const ops=this._pending.splice(0);const tx=this._createTransaction(true);const promises=ops.map(op=>{if(op.action==="set"){return this._set(tx,op.path,op.node)}else if(op.action==="remove"){return this._remove(tx,op.path)}else{throw new Error("Unknown pending operation")}});return Promise.all(promises).then(()=>{tx.commit&&tx.commit()}).catch(err=>{console.error(err);tx.abort&&tx.abort()})}rollback(err){this._pending=[];return Promise.resolve()}get(path){const tx=this._createTransaction(false);const r1=_requestToPromise(tx.objectStore("nodes").get(path));const r2=_requestToPromise(tx.objectStore("content").get(path));return Promise.all([r1,r2]).then(results=>{tx.commit&&tx.commit();const info=results[0];if(!info){return null}const node=info.metadata;node.value=results[1];return node}).catch(err=>{tx.abort&&tx.abort();console.error(`IndexedDB get error`,err);throw err})}set(path,node){this._pending.push({action:"set",path:path,node:node});return Promise.resolve()}remove(path){this._pending.push({action:"remove",path:path});return Promise.resolve()}_set(tx,path,node){const copy={};const value=node.value;Object.assign(copy,node);delete copy.value;const metadata=copy;const obj={path:path,metadata:metadata};const r1=_requestToPromise(tx.objectStore("nodes").put(obj));const r2=_requestToPromise(tx.objectStore("content").put(value,path));return Promise.all([r1,r2])}_remove(tx,path){const r1=_requestToPromise(tx.objectStore("content").delete(path));const r2=_requestToPromise(tx.objectStore("nodes").delete(path));return Promise.all([r1,r2])}childrenOf(path,include,checkCallback,addCallback){return new Promise((resolve,reject)=>{const pathInfo=CustomStorageHelpers.PathInfo.get(path);const tx=this._createTransaction(false);const store=tx.objectStore("nodes");const query=IDBKeyRange.lowerBound(path,true);const cursor=include.metadata?store.openCursor(query):store.openKeyCursor(query);cursor.onerror=e=>{tx.abort&&tx.abort();reject(e)};cursor.onsuccess=async e=>{const otherPath=cursor.result?cursor.result.key:null;let keepGoing=true;if(otherPath===null){keepGoing=false}else if(!pathInfo.isAncestorOf(otherPath)){keepGoing=false}else if(pathInfo.isParentOf(otherPath)&&checkCallback(otherPath)){let node;if(include.metadata){const valueCursor=cursor;const data=valueCursor.result.value;node=data.metadata;if(include.value){const req=tx.objectStore("content").get(otherPath);node.value=await new Promise((resolve,reject)=>{req.onerror=e=>{resolve(null)};req.onsuccess=e=>{resolve(req.result)}})}}keepGoing=addCallback(otherPath,node)}if(keepGoing){try{cursor.result.continue()}catch(err){keepGoing=false}}if(!keepGoing){tx.commit&&tx.commit();resolve()}}})}descendantsOf(path,include,checkCallback,addCallback){return new Promise((resolve,reject)=>{const pathInfo=CustomStorageHelpers.PathInfo.get(path);const tx=this._createTransaction(false);const store=tx.objectStore("nodes");const query=IDBKeyRange.lowerBound(path,true);const cursor=include.metadata?store.openCursor(query):store.openKeyCursor(query);cursor.onerror=e=>{tx.abort&&tx.abort();reject(e)};cursor.onsuccess=async e=>{const otherPath=cursor.result?cursor.result.key:null;let keepGoing=true;if(otherPath===null){keepGoing=false}else if(!pathInfo.isAncestorOf(otherPath)){keepGoing=false}else if(checkCallback(otherPath)){let node;if(include.metadata){const valueCursor=cursor;const data=valueCursor.result.value;node=data.metadata;if(include.value){const req=tx.objectStore("content").get(otherPath);node.value=await new Promise((resolve,reject)=>{req.onerror=e=>{resolve(null)};req.onsuccess=e=>{resolve(req.result)}})}}keepGoing=addCallback(otherPath,node)}if(keepGoing){try{cursor.result.continue()}catch(err){keepGoing=false}}if(!keepGoing){tx.commit&&tx.commit();resolve()}}})}}module.exports={BrowserAceBase:BrowserAceBase}},{"./acebase-local":31,"./storage-custom":38}],31:[function(require,module,exports){const{AceBaseBase:AceBaseBase,AceBaseSettings:AceBaseSettings}=require("acebase-core");const{StorageSettings:StorageSettings}=require("./storage");const{LocalApi:LocalApi}=require("./api-local");const{CustomStorageSettings:CustomStorageSettings,CustomStorageTransaction:CustomStorageTransaction,CustomStorageHelpers:CustomStorageHelpers,ICustomStorageNode:ICustomStorageNode,ICustomStorageNodeMetaData:ICustomStorageNodeMetaData}=require("./storage-custom");class AceBaseLocalSettings{constructor(options){if(!options){options={}}this.logLevel=options.logLevel||"log";this.storage=options.storage}}class AceBase extends AceBaseBase{constructor(dbname,options){options=new AceBaseLocalSettings(options);super(dbname,options);const apiSettings={db:this,storage:options.storage,logLevel:options.logLevel};this.api=new LocalApi(dbname,apiSettings,ready=>{this.emit("ready")})}static WithLocalStorage(dbname,settings){settings=settings||{};if(!settings.logLevel){settings.logLevel="error"}const localStorage=settings.provider?settings.provider:settings.temp?window.localStorage:window.sessionStorage;const storageSettings=new CustomStorageSettings({name:"LocalStorage",locking:true,ready(){return Promise.resolve()},getTransaction(target){const context={debug:true,dbname:dbname,localStorage:localStorage};const transaction=new LocalStorageTransaction(context,target);return Promise.resolve(transaction)}});return new AceBase(dbname,{logLevel:settings.logLevel,storage:storageSettings})}}class LocalStorageTransaction extends CustomStorageTransaction{constructor(context,target){super(target);this.context=context;this._storageKeysPrefix=`${this.context.dbname}.acebase::`}commit(){return Promise.resolve()}rollback(err){return Promise.resolve()}get(path){return new Promise(resolve=>{const json=this.context.localStorage.getItem(this.getStorageKeyForPath(path));const val=JSON.parse(json);resolve(val)})}set(path,val){return new Promise(resolve=>{const json=JSON.stringify(val);this.context.localStorage.setItem(this.getStorageKeyForPath(path),json);resolve()})}remove(path){return new Promise(resolve=>{this.context.localStorage.removeItem(this.getStorageKeyForPath(path));resolve()})}childrenOf(path,include,checkCallback,addCallback){return new Promise(resolve=>{const pathInfo=CustomStorageHelpers.PathInfo.get(path);for(let i=0;i{const pathInfo=CustomStorageHelpers.PathInfo.get(path);for(let i=0;i{}}){if(typeof options!=="object"){options={}}if(typeof options.snapshots==="undefined"){options.snapshots=false}const sortMatches=matches=>{matches.sort((a,b)=>{const compare=i=>{const o=query.order[i];let left=a.val[o.key];let right=b.val[o.key];if(typeof left==="undefined"&&typeof right!=="undefined"){return o.ascending?-1:1}if(typeof left!=="undefined"&&typeof right==="undefined"){return o.ascending?1:-1}if(typeof left==="undefined"&&typeof right==="undefined"){return 0}if(left==right){if(iright){return o.ascending?1:-1}};return compare(0)})};const loadResultsData=(preResults,options)=>{if(preResults.length===0){return Promise.resolve([])}const maxBatchSize=50;let batches=[];const items=preResults.map((result,index)=>({path:result.path,index:index}));while(items.length>0){let batchItems=items.splice(0,maxBatchSize);batches.push(batchItems)}const results=[];const nextBatch=()=>{const batch=batches.shift();return Promise.all(batch.map(item=>{const{path:path,index:index}=item;return Node.getValue(this.storage,path,options).then(val=>{if(val===null){this.storage.debug.warn(`Indexed result "/${path}" does not have a record!`);return}const result={path:path,val:val};if(stepsExecuted.sorted){results[index]=result}else{results.push(result);if(!stepsExecuted.skipped&&results.length>query.skip+query.take){sortMatches(results);results.pop()}}})})).then(()=>{if(batches.length>0){return nextBatch()}})};return nextBatch().then(()=>{return results})};const isWildcardPath=path.includes("*");const availableIndexes=this.storage.indexes.get(path);const usingIndexes=[];query.filters.forEach(filter=>{if(filter.index){return}const indexesOnKey=availableIndexes.filter(index=>index.key===filter.key).filter(index=>{return index.validOperators.includes(filter.op)});if(indexesOnKey.length>=1){const otherFilterKeys=query.filters.filter(f=>f!==filter).map(f=>f.key);const sortKeys=query.order.map(o=>o.key).filter(key=>key!==filter.key);const beneficialIndexes=indexesOnKey.map(index=>{const availableKeys=index.includeKeys.concat(index.key);const forOtherFilters=availableKeys.filter(key=>otherFilterKeys.indexOf(key)>=0);const forSorting=availableKeys.filter(key=>sortKeys.indexOf(key)>=0);const forBoth=forOtherFilters.concat(forSorting.filter(index=>forOtherFilters.indexOf(index)<0));const points={filters:forOtherFilters.length,sorting:forSorting.length*(query.take>0?forSorting.length:1),both:forBoth.length*forBoth.length,get total(){return this.filters+this.sorting+this.both}};return{index:index,points:points.total,filterKeys:forOtherFilters,sortKeys:forSorting}});beneficialIndexes.sort((a,b)=>a.points>b.points?-1:1);const bestBenificialIndex=beneficialIndexes[0];filter.index=bestBenificialIndex.index;bestBenificialIndex.filterKeys.forEach(key=>{query.filters.filter(f=>f!==filter&&f.key===key).forEach(f=>{if(!DataIndex.validOperators.includes(f.op)){return}f.indexUsage="filter";f.index=bestBenificialIndex.index})});bestBenificialIndex.sortKeys.forEach(key=>{query.order.filter(s=>s.key===key).forEach(s=>{s.index=bestBenificialIndex.index})})}if(filter.index){usingIndexes.push({index:filter.index,description:filter.index.description})}});if(query.order.length>0&&query.take>0){query.order.forEach(sort=>{if(sort.index){return}sort.index=availableIndexes.filter(index=>index.key===sort.key).find(index=>index.type==="normal")})}const indexDescriptions=usingIndexes.map(index=>index.description).join(", ");usingIndexes.length>0&&this.storage.debug.log(`Using indexes for query: ${indexDescriptions}`);const tableScanFilters=query.filters.filter(filter=>!filter.index);const specialOpsRegex=/^[a-z]+\:/i;if(tableScanFilters.some(filter=>specialOpsRegex.test(filter.op))){const f=tableScanFilters.find(filter=>specialOpsRegex.test(filter.op));const err=new Error(`query contains operator "${f.op}" which requires a special index that was not found on path "${path}", key "${f.key}"`);return Promise.reject(err)}const allowedTableScanOperators=["<","<=","==","!=",">=",">","like","!like","in","!in","matches","!matches","between","!between","has","!has","contains","!contains","exists","!exists"];for(let i=0;i0){const keys=tableScanFilters.reduce((keys,f)=>{if(keys.indexOf(f.key)<0){keys.push(f.key)}return keys},[]).map(key=>`"${key}"`);const err=new Error(`This wildcard path query on "/${path}" requires index(es) on key(s): ${keys.join(", ")}. Create the index(es) and retry`);return Promise.reject(err)}const indexScanPromises=[];query.filters.forEach(filter=>{if(filter.index&&filter.indexUsage!=="filter"){let promise=filter.index.query(filter.op,filter.compare).then(results=>{options.eventHandler&&options.eventHandler({name:"stats",type:"index_query",source:filter.index.description,stats:results.stats});if(results.hints.length>0){options.eventHandler&&options.eventHandler({name:"hints",type:"index_query",source:filter.index.description,hints:results.hints})}return results});const resultFilters=query.filters.filter(f=>f.index===filter.index&&f.indexUsage==="filter");if(resultFilters.length>0){promise=promise.then(results=>{resultFilters.forEach(filter=>{results=results.filterMetadata(filter.key,filter.op,filter.compare)});return results})}indexScanPromises.push(promise)}});const stepsExecuted={filtered:query.filters.length===0,skipped:query.skip===0,taken:query.take===0,sorted:query.order.length===0,preDataLoaded:false,dataLoaded:false};if(query.filters.length===0&&query.take===0){this.storage.debug.error(`Filterless queries must use .take to limit the results. Defaulting to 100 for query on path "${path}"`);query.take=100}if(query.filters.length===0&&query.order.length>0&&query.order[0].index){const sortIndex=query.order[0].index;this.storage.debug.log(`Using index for sorting: ${sortIndex.description}`);const promise=sortIndex.take(query.skip,query.take,query.order[0].ascending).then(results=>{options.eventHandler&&options.eventHandler({name:"stats",type:"sort_index_take",source:filter.index.description,stats:results.stats});if(results.hints.length>0){options.eventHandler&&options.eventHandler({name:"hints",type:"sort_index_take",source:filter.index.description,hints:results.hints})}return results});indexScanPromises.push(promise);stepsExecuted.skipped=true;stepsExecuted.taken=true;stepsExecuted.sorted=true}return Promise.all(indexScanPromises).then(indexResultSets=>{let indexedResults=[];if(indexResultSets.length===1){const resultSet=indexResultSets[0];indexedResults=resultSet.map(match=>{const result={key:match.key,path:match.path,val:{[resultSet.filterKey]:match.value}};match.metadata&&Object.assign(result.val,match.metadata);return result});stepsExecuted.filtered=true}else if(indexResultSets.length>1){indexResultSets.sort((a,b)=>a.length{const result={key:match.key,path:match.path,val:{[shortestSet.filterKey]:match.value}};const matchedInAllSets=otherSets.every(set=>set.findIndex(m=>match.path===match.path)>=0);if(matchedInAllSets){match.metadata&&Object.assign(result.val,match.metadata);otherSets.forEach(set=>{const otherResult=set.find(r=>r.path===result.path);result.val[set.filterKey]=otherResult.value;otherResult.metadata&&Object.assign(result.val,otherResult.metadata)});results.push(result)}return results},[]);stepsExecuted.filtered=true}if(isWildcardPath||indexScanPromises.length>0&&tableScanFilters.length===0){if(query.order.length===0||query.order.every(o=>o.index)){stepsExecuted.preDataLoaded=true;if(!stepsExecuted.sorted&&query.order.length>0){sortMatches(indexedResults)}stepsExecuted.sorted=true;if(!stepsExecuted.skipped&&query.skip>0){indexedResults=indexedResults.slice(query.skip)}if(!stepsExecuted.taken&&query.take>0){indexedResults=indexedResults.slice(0,query.take)}stepsExecuted.skipped=true;stepsExecuted.taken=true;if(!options.snapshots){return indexedResults}const childOptions={include:options.include,exclude:options.exclude,child_objects:options.child_objects};return loadResultsData(indexedResults,childOptions).then(results=>{stepsExecuted.dataLoaded=true;return results})}if(options.snapshots||!stepsExecuted.sorted){const loadPartialResults=query.order.length>0;const childOptions=loadPartialResults?{include:query.order.map(order=>order.key)}:{include:options.include,exclude:options.exclude,child_objects:options.child_objects};return loadResultsData(indexedResults,childOptions).then(results=>{if(query.order.length>0){sortMatches(results)}stepsExecuted.sorted=true;if(query.skip>0){results=results.slice(query.skip)}if(query.take>0){results=results.slice(0,query.take)}stepsExecuted.skipped=true;stepsExecuted.taken=true;if(options.snapshots&&loadPartialResults){return loadResultsData(results,{include:options.include,exclude:options.exclude,child_objects:options.child_objects})}return results})}else{return indexedResults}}let indexKeyFilter;if(indexedResults.length>0){indexKeyFilter=indexedResults.map(result=>result.key)}const promises=[];let matches=[];let preliminaryStop=false;const loadPartialData=query.order.length>0;const childOptions=loadPartialData?{include:query.order.map(order=>order.key)}:{include:options.include,exclude:options.exclude,child_objects:options.child_objects};return Node.getChildren(this.storage,path,indexKeyFilter).next(child=>{if(child.type===Node.VALUE_TYPES.OBJECT){if(!child.address){return}if(preliminaryStop){return false}const p=Node.matches(this.storage,child.address.path,tableScanFilters).then(isMatch=>{if(!isMatch){return null}const childPath=child.address.path;if(options.snapshots||query.order.length>0){return Node.getValue(this.storage,childPath,childOptions).then(val=>{return{path:childPath,val:val}})}else{return{path:childPath}}}).then(result=>{if(result!==null){matches.push(result);if(query.take>0&&matches.length>query.take+query.skip){if(query.order.length>0){sortMatches(matches)}else{preliminaryStop=true}matches.pop()}}});promises.push(p)}}).catch(reason=>{this.storage.debug.warn(`Error getting child stream: ${reason}`);return[]}).then(()=>{return Promise.all(promises).then(()=>{stepsExecuted.preDataLoaded=loadPartialData;stepsExecuted.dataLoaded=!loadPartialData;if(query.order.length>0){sortMatches(matches)}stepsExecuted.sorted=true;if(query.skip>0){matches=matches.slice(query.skip)}stepsExecuted.skipped=true;if(query.take>0){matches=matches.slice(0,query.take)}stepsExecuted.taken=true;if(!stepsExecuted.dataLoaded){return loadResultsData(matches,{include:options.include,exclude:options.exclude,child_objects:options.child_objects}).then(results=>{stepsExecuted.dataLoaded=true;return results})}return matches})})}).then(matches=>{if(!stepsExecuted.sorted&&query.order.length>0){sortMatches(matches)}if(!options.snapshots){matches=matches.map(match=>match.path)}if(!stepsExecuted.skipped&&query.skip>0){matches=matches.slice(query.skip)}if(!stepsExecuted.taken&&query.take>0){matches=matches.slice(0,query.take)}if(options.monitor===true){options.monitor={add:true,change:true,remove:true}}if(typeof options.monitor==="object"&&(options.monitor.add||options.monitor.change||options.monitor.remove)){const matchedPaths=options.snapshots?matches.map(match=>match.path):matches.slice();const ref=this.db.ref(path);const removeMatch=path=>{const index=matchedPaths.indexOf(path);if(index<0){return}matchedPaths.splice(index,1)};const addMatch=path=>{if(matchedPaths.includes(path)){return}matchedPaths.push(path)};const stopMonitoring=()=>{this.unsubscribe(ref.path,"notify_child_changed",childChangedCallback);this.unsubscribe(ref.path,"notify_child_added",childAddedCallback);this.unsubscribe(ref.path,"notify_child_removed",childRemovedCallback)};const childChangedCallback=(err,path,newValue,oldValue)=>{const wasMatch=matchedPaths.includes(path);let keepMonitoring=true;const checkKeys=[];query.filters.forEach(f=>!checkKeys.includes(f.key)&&checkKeys.push(f.key));const seenKeys=[];typeof oldValue==="object"&&Object.keys(oldValue).forEach(key=>!seenKeys.includes(key)&&seenKeys.push(key));typeof newValue==="object"&&Object.keys(newValue).forEach(key=>!seenKeys.includes(key)&&seenKeys.push(key));const missingKeys=[];let isMatch=seenKeys.every(key=>{if(!checkKeys.includes(key)){return true}const filters=query.filters.filter(filter=>filter.key===key);return filters.every(filter=>{if(allowedTableScanOperators.includes(filter.op)){return this.storage.test(newValue[key],filter.op,filter.compare)}if(filter.index.constructor.name==="FullTextDataIndex"&&filter.index.localeKey&&!seenKeys.includes(filter.index.localeKey)){missingKeys.push(filter.index.localeKey);return true}return filter.index.test(newValue,filter.op,filter.compare)})});if(isMatch){missingKeys.push(...checkKeys.filter(key=>!seenKeys.includes(key)));let promise=Promise.resolve(true);if(!wasMatch&&missingKeys.length>0){const filterQueue=query.filters.filter(f=>missingKeys.includes(f.key));const simpleFilters=filterQueue.filter(f=>allowedTableScanOperators.includes(f.op));const indexFilters=filterQueue.filter(f=>!allowedTableScanOperators.includes(f.op));const processFilters=()=>{const checkIndexFilters=()=>{const keysToLoad=indexFilters.reduce((keys,filter)=>{if(!keys.includes(filter.key)){keys.push(filter.key)}if(filter.index.constructor.name==="FullTextDataIndex"&&filter.index.localeKey&&!keys.includes(filter.index.localeKey)){keys.push(filter.index.localeKey)}return keys},[]);return Node.getValue(this.storage,path,{include:keysToLoad}).then(val=>{if(val===null){return false}return indexFilters.every(filter=>filter.index.test(val,filter.op,filter.compare))})};if(simpleFilters.length>0){return Node.matches(this.storage,path,simpleFilters).then(isMatch=>{if(isMatch){if(indexFilters.length===0){return true}return checkIndexFilters()}return false})}else{return checkIndexFilters()}};promise=processFilters()}return promise.then(isMatch=>{if(isMatch){if(!wasMatch){addMatch(path)}let gotValue=value=>{if(wasMatch&&options.monitor.change){keepMonitoring=options.eventHandler({name:"change",path:path,value:value})}else if(!wasMatch&&options.monitor.add){keepMonitoring=options.eventHandler({name:"add",path:path,value:value})}if(keepMonitoring===false){stopMonitoring()}};if(options.snapshots){const loadOptions={include:options.include,exclude:options.exclude,child_objects:options.child_objects};return this.storage.getNodeValue(path,loadOptions).then(gotValue)}else{return gotValue(newValue)}}else if(wasMatch){removeMatch(path);if(options.monitor.remove){keepMonitoring=options.eventHandler({name:"remove",path:path,value:oldValue})}}if(keepMonitoring===false){stopMonitoring()}})}else{if(wasMatch){removeMatch(path);if(options.monitor.remove){keepMonitoring=options.eventHandler({name:"remove",path:path,value:oldValue});if(keepMonitoring===false){stopMonitoring()}}}}};const childAddedCallback=(err,path,newValue,oldValue)=>{let isMatch=query.filters.every(filter=>{if(allowedTableScanOperators.includes(filter.op)){return this.storage.test(newValue[filter.key],filter.op,filter.compare)}else{return filter.index.test(newValue,filter.op,filter.compare)}});let keepMonitoring=true;if(isMatch){addMatch(path);if(options.monitor.add){keepMonitoring=options.eventHandler({name:"add",path:path,value:options.snapshots?newValue:null})}}if(keepMonitoring===false){stopMonitoring()}};const childRemovedCallback=(err,path,newValue,oldValue)=>{let keepMonitoring=true;removeMatch(path);if(options.monitor.remove){keepMonitoring=options.eventHandler({name:"remove",path:path,value:options.snapshots?oldValue:null})}if(keepMonitoring===false){stopMonitoring()}};if(options.monitor.add||options.monitor.change||options.monitor.remove){this.subscribe(ref.path,"notify_child_changed",childChangedCallback)}if(options.monitor.remove){this.subscribe(ref.path,"notify_child_removed",childRemovedCallback)}if(options.monitor.add){this.subscribe(ref.path,"notify_child_added",childAddedCallback)}}return matches})}createIndex(path,key,options){return this.storage.indexes.create(path,key,options)}getIndexes(){return Promise.resolve(this.storage.indexes.list())}reflect(path,type,args){const getChildren=(path,limit=50,skip=0)=>{if(typeof limit==="string"){limit=parseInt(limit)}if(typeof skip==="string"){skip=parseInt(skip)}const children=[];let n=0,stop=skip+limit;return Node.getChildren(this.storage,path).next(childInfo=>{n++;if(limit===0||n<=stop&&n>skip){children.push({key:typeof childInfo.key==="string"?childInfo.key:childInfo.index,type:childInfo.valueTypeName,value:childInfo.value,address:typeof childInfo.address==="object"&&"pageNr"in childInfo.address?{pageNr:childInfo.address.pageNr,recordNr:childInfo.address.recordNr}:undefined})}if(limit>0&&n>stop){return false}}).then(()=>{return{more:limit!==0&&n>stop,list:children}})};switch(type){case"children":{return getChildren(path,args.limit,args.skip)}case"info":{const info={key:"",exists:false,type:"unknown",value:undefined,children:{more:false,list:[]}};return Node.getInfo(this.storage,path).then(nodeInfo=>{info.key=nodeInfo.key;info.exists=nodeInfo.exists;info.type=nodeInfo.valueTypeName;info.value=nodeInfo.value;let hasChildren=nodeInfo.exists&&nodeInfo.address&&[Node.VALUE_TYPES.OBJECT,Node.VALUE_TYPES.ARRAY].includes(nodeInfo.type);if(hasChildren){return getChildren(path,args.child_limit,args.child_skip)}}).then(children=>{info.children=children;return info})}}}export(path,stream,options={format:"json"}){return this.storage.exportNode(path,stream,options)}}module.exports={LocalApi:LocalApi}},{"./acebase-local":31,"./data-index":40,"./node":37,"./storage":39,"./storage-acebase":40,"./storage-custom":38,"./storage-mssql":40,"./storage-sqlite":40,"acebase-core":11}],33:[function(require,module,exports){const{DataReference:DataReference,DataSnapshot:DataSnapshot,EventSubscription:EventSubscription,PathReference:PathReference,TypeMappings:TypeMappings,TypeMappingOptions:TypeMappingOptions}=require("acebase-core");const{AceBaseLocalSettings:AceBaseLocalSettings}=require("./acebase-local");const{BrowserAceBase:BrowserAceBase}=require("./acebase-browser");const{CustomStorageSettings:CustomStorageSettings,CustomStorageTransaction:CustomStorageTransaction,CustomStorageHelpers:CustomStorageHelpers}=require("./storage-custom");const acebase={AceBase:BrowserAceBase,AceBaseLocalSettings:AceBaseLocalSettings,DataReference:DataReference,DataSnapshot:DataSnapshot,EventSubscription:EventSubscription,PathReference:PathReference,TypeMappings:TypeMappings,TypeMappingOptions:TypeMappingOptions,CustomStorageSettings:CustomStorageSettings,CustomStorageTransaction:CustomStorageTransaction,CustomStorageHelpers:CustomStorageHelpers};window.acebase=acebase;window.AceBase=BrowserAceBase;module.exports=acebase},{"./acebase-browser":30,"./acebase-local":31,"./storage-custom":38,"acebase-core":11}],34:[function(require,module,exports){const{VALUE_TYPES:VALUE_TYPES,getValueTypeName:getValueTypeName}=require("./node-value-types");const{PathInfo:PathInfo}=require("acebase-core");class NodeInfo{constructor(info){this.path=info.path;this.type=info.type;this.index=info.index;this.key=info.key;this.exists=info.exists;this.address=info.address;this.value=info.value;if(typeof this.path==="string"&&(typeof this.key==="undefined"&&typeof this.index==="undefined")){let pathInfo=PathInfo.get(this.path);if(typeof pathInfo.key==="number"){this.index=pathInfo.key}else{this.key=pathInfo.key}}if(typeof this.exists==="undefined"){this.exists=true}}get valueType(){return this.type}get valueTypeName(){return getValueTypeName(this.valueType)}toString(){if(!this.exists){return`"${this.path}" doesn't exist`}if(this.address){return`"${this.path}" is ${this.valueTypeName} stored at ${this.address.pageNr},${this.address.recordNr}`}else{return`"${this.path}" is ${this.valueTypeName} with value ${this.value}`}}}module.exports={NodeInfo:NodeInfo}},{"./node-value-types":36,"acebase-core":11}],35:[function(require,module,exports){const{PathInfo:PathInfo}=require("acebase-core");const SECOND=1e3;const MINUTE=6e4;const DEBUG_MODE=false;const LOCK_TIMEOUT=DEBUG_MODE?15*MINUTE:90*SECOND;const LOCK_STATE={PENDING:"pending",LOCKED:"locked",EXPIRED:"expired",DONE:"done"};class NodeLocker{constructor(){this._locks=[]}_allowLock(path,tid,forWriting){const pathInfo=PathInfo.get(path);const existing=this._locks.find(otherLock=>otherLock.tid===tid&&otherLock.state===LOCK_STATE.LOCKED&&(otherLock.path===path||pathInfo.isDescendantOf(otherLock.path))&&(otherLock.forWriting||!forWriting));if(typeof existing==="object"){return{allow:true}}const conflict=this._locks.filter(otherLock=>otherLock.tid!==tid&&otherLock.state===LOCK_STATE.LOCKED).find(otherLock=>{return(forWriting||otherLock.forWriting)&&(path===otherLock.path||pathInfo.isDescendantOf(otherLock.path))});const clashes=typeof conflict!=="undefined";return{allow:!clashes,conflict:conflict}}_processLockQueue(){const pending=this._locks.filter(lock=>lock.state===LOCK_STATE.PENDING&&(lock.waitingFor===null||lock.waitingFor.state!==LOCK_STATE.LOCKED)).sort((a,b)=>{if(a.priority&&!b.priority){return-1}else if(!a.priority&&b.priority){return 1}return a.requested{const check=this._allowLock(lock.path,lock.tid,lock.forWriting);lock.waitingFor=check.conflict||null;if(check.allow){this.lock(lock).then(lock.resolve).catch(lock.reject)}})}lock(path,tid,forWriting=true,comment="",options={withPriority:false,noTimeout:false}){let lock,proceed;if(path instanceof NodeLock){lock=path;lock.comment=`(retry: ${lock.comment})`;proceed=true}else if(this._locks.findIndex(l=>l.tid===tid&&l.state===LOCK_STATE.EXPIRED)>=0){return Promise.reject(new Error(`lock on tid ${tid} has expired, not allowed to continue`))}else{lock=new NodeLock(this,path,tid,forWriting,options.withPriority===true);lock.comment=comment;this._locks.push(lock);const check=this._allowLock(path,tid,forWriting);lock.waitingFor=check.conflict||null;proceed=check.allow}if(proceed){lock.state=LOCK_STATE.LOCKED;if(typeof lock.granted==="number"){}else{lock.granted=Date.now();if(options.noTimeout!==true){lock.expires=Date.now()+LOCK_TIMEOUT;lock.timeout=setTimeout(()=>{if(lock.state!==LOCK_STATE.LOCKED){return}console.error(`lock :: ${lock.forWriting?"write":"read"} lock on path "/${lock.path}" by tid ${lock.tid} took too long, ${lock.comment}`);lock.state=LOCK_STATE.EXPIRED;this._processLockQueue()},LOCK_TIMEOUT)}}return Promise.resolve(lock)}else{console.assert(lock.state===LOCK_STATE.PENDING);const p=new Promise((resolve,reject)=>{lock.resolve=resolve;lock.reject=reject});return p}}unlock(lockOrId,comment,processQueue=true){let lock,i;if(lockOrId instanceof NodeLock){lock=lockOrId;i=this._locks.indexOf(lock)}else{let id=lockOrId;i=this._locks.findIndex(l=>l.id===id);lock=this._locks[i]}if(i<0){const msg=`lock on "/${lock.path}" for tid ${lock.tid} wasn't found; ${comment}`;return Promise.reject(new Error(msg))}lock.state=LOCK_STATE.DONE;clearTimeout(lock.timeout);this._locks.splice(i,1);processQueue&&this._processLockQueue();return Promise.resolve(lock)}list(){return this._locks||[]}isAllowed(path,tid,forWriting){return this._allowLock(path,tid,forWriting).allow}}let lastid=0;class NodeLock{static get LOCK_STATE(){return LOCK_STATE}constructor(locker,path,tid,forWriting,priority=false){this.locker=locker;this.path=path;this.tid=tid;this.forWriting=forWriting;this.priority=priority;this.state=LOCK_STATE.PENDING;this.requested=Date.now();this.granted=undefined;this.expires=undefined;this.comment="";this.waitingFor=null;this.id=++lastid}release(comment){return this.locker.unlock(this,comment||this.comment)}moveToParent(){const parentPath=PathInfo.get(this.path).parentPath;const allowed=this.locker.isAllowed(parentPath,this.tid,this.forWriting);if(allowed){this.waitingFor=null;this.path=parentPath;this.comment=`moved to parent: ${this.comment}`;return Promise.resolve(this)}else{this.locker.unlock(this,`moveLockToParent: ${this.comment}`,false);return this.locker.lock(parentPath,this.tid,this.forWriting,`moved to parent (queued): ${this.comment}`,{withPriority:true}).then(newLock=>{return newLock})}}moveTo(otherPath,forWriting){const allowed=this.locker.isAllowed(otherPath,this.tid,forWriting);if(allowed){this.waitingFor=null;this.path=otherPath;this.forWriting=forWriting;this.comment=`moved to "/${otherPath}": ${this.comment}`;return Promise.resolve(this)}else{this.locker.unlock(this,`moving to "/${otherPath}": ${this.comment}`,false);return this.locker.lock(otherPath,this.tid,forWriting,`moved to "/${otherPath}" (queued): ${this.comment}`,{withPriority:true}).then(newLock=>{return newLock})}}}module.exports={NodeLocker:NodeLocker,NodeLock:NodeLock}},{"acebase-core":11}],36:[function(require,module,exports){const VALUE_TYPES={OBJECT:1,ARRAY:2,NUMBER:3,BOOLEAN:4,STRING:5,DATETIME:6,BINARY:8,REFERENCE:9};function getValueTypeName(valueType){switch(valueType){case VALUE_TYPES.ARRAY:return"array";case VALUE_TYPES.BINARY:return"binary";case VALUE_TYPES.BOOLEAN:return"boolean";case VALUE_TYPES.DATETIME:return"date";case VALUE_TYPES.NUMBER:return"number";case VALUE_TYPES.OBJECT:return"object";case VALUE_TYPES.REFERENCE:return"reference";case VALUE_TYPES.STRING:return"string";default:"unknown"}}module.exports={VALUE_TYPES:VALUE_TYPES,getValueTypeName:getValueTypeName}},{}],37:[function(require,module,exports){const{Storage:Storage}=require("./storage");const{NodeInfo:NodeInfo}=require("./node-info");const{VALUE_TYPES:VALUE_TYPES,getValueTypeName:getValueTypeName}=require("./node-value-types");const colors=require("colors");class Node{static get VALUE_TYPES(){return VALUE_TYPES}static getInfo(storage,path,options={no_cache:false}){if(options&&!options.no_cache){let cachedInfo=storage.nodeCache.find(path);if(cachedInfo){return Promise.resolve(cachedInfo)}}return storage.getNodeInfo(path).then(info=>{if(options&&!options.no_cache){storage.nodeCache.update(info)}return info})}static update(storage,path,value,options={merge:true}){if(options.merge){return storage.updateNode(path,value)}else{return storage.setNode(path,value)}}static exists(storage,path){return storage.getNodeInfo(path).then(nodeInfo=>{return nodeInfo.exists})}static getValue(storage,path,options={include:undefined,exclude:undefined,child_objects:true}){if(!options){options={}}if(typeof options.include!=="undefined"&&!(options.include instanceof Array)){throw new TypeError(`options.include must be an array of key names`)}if(typeof options.exclude!=="undefined"&&!(options.exclude instanceof Array)){throw new TypeError(`options.exclude must be an array of key names`)}if(["undefined","boolean"].indexOf(typeof options.child_objects)<0){throw new TypeError(`options.child_objects must be a boolean`)}return storage.getNodeValue(path,options)}static getChildInfo(storage,path,childKeyOrIndex){let childInfo;return storage.getChildren(path,{keyFilter:[childKeyOrIndex]}).next(info=>{childInfo=info}).then(()=>{return childInfo})}static getChildren(storage,path,keyFilter=undefined){return storage.getChildren(path,{keyFilter:keyFilter})}static remove(storage,path){return storage.removeNode(path)}static set(storage,path,value){return Node.update(storage,path,value,{merge:false})}static transaction(storage,path,callback){return storage.transactNode(path,callback)}static matches(storage,path,criteria,options){return storage.matchNode(path,criteria,options)}}class NodeChange{static get CHANGE_TYPE(){return{UPDATE:"update",DELETE:"delete",INSERT:"insert"}}constructor(keyOrIndex,changeType,oldValue,newValue){this.keyOrIndex=keyOrIndex;this.changeType=changeType;this.oldValue=oldValue;this.newValue=newValue}}class NodeChangeTracker{constructor(path){this.path=path;this._changes=[];this._oldValue=undefined;this._newValue=undefined}addDelete(keyOrIndex,oldValue){this._changes.push(new NodeChange(keyOrIndex,NodeChange.CHANGE_TYPE.DELETE,oldValue,null))}addUpdate(keyOrIndex,oldValue,newValue){this._changes.push(new NodeChange(keyOrIndex,NodeChange.CHANGE_TYPE.UPDATE,oldValue,newValue))}addInsert(keyOrIndex,newValue){this._changes.push(new NodeChange(keyOrIndex,NodeChange.CHANGE_TYPE.INSERT,null,newValue))}add(keyOrIndex,currentValue,newValue){if(currentValue===null){if(newValue===null){throw new Error(`Wrong logic for node change on "${this.nodeInfo.path}/${keyOrIndex}" - both old and new values are null`)}this.addInsert(keyOrIndex,newValue)}else if(newValue===null){this.addDelete(keyOrIndex,currentValue)}else{this.addUpdate(keyOrIndex,currentValue,newValue)}}get updates(){return this._changes.filter(change=>change.changeType===NodeChange.CHANGE_TYPE.UPDATE)}get deletes(){return this._changes.filter(change=>change.changeType===NodeChange.CHANGE_TYPE.DELETE)}get inserts(){return this._changes.filter(change=>change.changeType===NodeChange.CHANGE_TYPE.INSERT)}get all(){return this._changes}get totalChanges(){return this._changes.length}get(keyOrIndex){return this._changes.find(change=>change.keyOrIndex===keyOrIndex)}hasChanged(keyOrIndex){return!!this.get(keyOrIndex)}get newValue(){if(typeof this._newValue==="object"){return this._newValue}if(typeof this._oldValue==="undefined"){throw new TypeError(`oldValue is not set`)}let newValue={};Object.keys(this.oldValue).forEach(key=>newValue[key]=oldValue[key]);this.deletes.forEach(change=>delete newValue[change.key]);this.updates.forEach(change=>newValue[change.key]=change.newValue);this.inserts.forEach(change=>newValue[change.key]=change.newValue);return newValue}set newValue(value){this._newValue=value}get oldValue(){if(typeof this._oldValue==="object"){return this._oldValue}if(typeof this._newValue==="undefined"){throw new TypeError(`newValue is not set`)}let oldValue={};Object.keys(this.newValue).forEach(key=>oldValue[key]=newValue[key]);this.deletes.forEach(change=>oldValue[change.key]=change.oldValue);this.updates.forEach(change=>oldValue[change.key]=change.oldValue);this.inserts.forEach(change=>delete oldValue[change.key]);return oldValue}set oldValue(value){this._oldValue=value}get typeChanged(){return typeof this.oldValue!==typeof this.newValue||this.oldValue instanceof Array&&!(this.newValue instanceof Array)||this.newValue instanceof Array&&!(this.oldValue instanceof Array)}static create(path,oldValue,newValue){const changes=new NodeChangeTracker(path);changes.oldValue=oldValue;changes.newValue=newValue;typeof oldValue==="object"&&Object.keys(oldValue).forEach(key=>{if(typeof newValue==="object"&&key in newValue&&newValue!==null){changes.add(key,oldValue[key],newValue[key])}else{changes.add(key,oldValue[key],null)}});typeof newValue==="object"&&Object.keys(newValue).forEach(key=>{if(typeof oldValue!=="object"||!(key in oldValue)||oldValue[key]===null){changes.add(key,null,newValue[key])}});return changes}}module.exports={Node:Node,NodeInfo:NodeInfo}},{"./node-info":34,"./node-value-types":36,"./storage":39,colors:22}],38:[function(require,module,exports){const{debug:debug,ID:ID,PathReference:PathReference,PathInfo:PathInfo,ascii85:ascii85}=require("acebase-core");const{NodeInfo:NodeInfo}=require("./node-info");const{NodeLocker:NodeLocker}=require("./node-lock");const{VALUE_TYPES:VALUE_TYPES}=require("./node-value-types");const{Storage:Storage,StorageSettings:StorageSettings,NodeNotFoundError:NodeNotFoundError}=require("./storage");class ICustomStorageNodeMetaData{constructor(){this.revision="";this.revision_nr=0;this.created=0;this.modified=0;this.type=0}}class ICustomStorageNode extends ICustomStorageNodeMetaData{constructor(){super();this.value=null}}class CustomStorageTransaction{constructor(target){this.target={get originalPath(){return target.path},path:target.path,get write(){return target.write}};this.id=ID.generate()}get(path){throw new Error(`CustomStorageTransaction.get must be overridden by subclass`)}set(path,node){throw new Error(`CustomStorageTransaction.set must be overridden by subclass`)}remove(path){throw new Error(`CustomStorageTransaction.remove must be overridden by subclass`)}childrenOf(path,include,checkCallback,addCallback){throw new Error(`CustomStorageTransaction.childrenOf must be overridden by subclass`)}descendantsOf(path,include,checkCallback,addCallback){throw new Error(`CustomStorageTransaction.descendantsOf must be overridden by subclass`)}getMultiple(paths){const map=new Map;return Promise.all(paths.map(path=>this.get(path).then(val=>map.set(path,val)))).then(done=>map)}async setMultiple(nodes){await Promise.all(paths.map(({path:path,node:node})=>this.set(path,node)))}async removeMultiple(paths){await Promise.all(paths.map(path=>this.remove(path)))}rollback(reason){throw new Error(`CustomStorageTransaction.rollback must be overridden by subclass`)}commit(){throw new Error(`CustomStorageTransaction.rollback must be overridden by subclass`)}async moveToParentPath(targetPath){const currentPath=this._lock&&this._lock.path||this.target.path;if(currentPath===targetPath){return targetPath}const pathInfo=CustomStorageHelpers.PathInfo.get(targetPath);if(pathInfo.isParentOf(currentPath)){if(this._lock){this._lock=await this._lock.moveToParent()}}else{throw new Error(`Locking issue. Locked path "${this._lock.path}" is not a child/descendant of "${targetPath}"`)}this.target.path=targetPath;return targetPath}}class CustomStorageSettings extends StorageSettings{constructor(settings){super(settings);settings=settings||{};if(typeof settings.ready!=="function"){throw new Error(`ready must be a function`)}if(typeof settings.getTransaction!=="function"){throw new Error(`getTransaction must be a function`)}this.name=settings.name;this.info=`${this.name||"CustomStorage"} realtime database`;this.locking=settings.locking!==false;this.ready=settings.ready;const useLocking=this.locking;const nodeLocker=useLocking?new NodeLocker:null;this.getTransaction=async({path:path,write:write})=>{const transaction=await settings.getTransaction({path:path,write:write});console.assert(typeof transaction.id==="string",`transaction id not set`);const rollback=transaction.rollback;const commit=transaction.commit;transaction.commit=async()=>{const ret=await commit.call(transaction);if(useLocking){await transaction._lock.release("commit")}return ret};transaction.rollback=async reason=>{const ret=await rollback.call(transaction,reason);if(useLocking){await transaction._lock.release("rollback")}return ret};if(useLocking){transaction._lock=await nodeLocker.lock(path,transaction.id,write,`${this.name}::getTransaction`)}return transaction}}}class CustomStorageNodeAddress{constructor(containerPath){this.path=containerPath}}class CustomStorageNodeInfo extends NodeInfo{constructor(info){super(info);this.address;this.revision=info.revision;this.revision_nr=info.revision_nr;this.created=info.created;this.modified=info.modified}}class CustomStorageHelpers{static ChildPathsSql(path,columnName="path"){const where=path===""?`${columnName} <> '' AND ${columnName} NOT LIKE '%/%'`:`(${columnName} LIKE '${path}/%' OR ${columnName} LIKE '${path}[%') AND ${columnName} NOT LIKE '${path}/%/%' AND ${columnName} NOT LIKE '${path}[%]/%' AND ${columnName} NOT LIKE '${path}[%][%'`;return where}static ChildPathsRegex(path){return new RegExp(`^${path}(?:/[^/[]+|[[0-9]+])$`)}static DescendantPathsSql(path,columnName="path"){const where=path===""?`${columnName} <> ''`:`${columnName} LIKE '${path}/%' OR ${columnName} LIKE '${path}[%'`;return where}static DescendantPathsRegex(path){return new RegExp(`^${path}(?:/[^/[]+|[[0-9]+])`)}static get PathInfo(){return PathInfo}}class CustomStorage extends Storage{constructor(dbname,settings){super(dbname,settings);this._init()}async _init(){this._customImplementation=this.settings;this.debug.log(`Database "${this.name}" details:`.intro);this.debug.log(`- Type: CustomStorage`);this.debug.log(`- Path: ${this.settings.path}`);this.debug.log(`- Max inline value size: ${this.settings.maxInlineValueSize}`.intro);this.debug.log(`- Autoremove undefined props: ${this.settings.removeVoidProperties}`);await this._customImplementation.ready();const transaction=await this._customImplementation.getTransaction({path:"",write:true});const info=await this.getNodeInfo("",{transaction:transaction});if(!info.exists){await this._writeNode("",{},{transaction:transaction})}await transaction.commit();if(this.indexes.supported){await this.indexes.load()}this.emit("ready")}_storeNode(path,node,options){const getTypedChildValue=val=>{if(val===null){throw new Error(`Not allowed to store null values. remove the property`)}else if(["string","number","boolean"].includes(typeof val)){return val}else if(val instanceof Date){return{type:VALUE_TYPES.DATETIME,value:val.getTime()}}else if(val instanceof PathReference){return{type:VALUE_TYPES.REFERENCE,value:child.path}}else if(val instanceof ArrayBuffer){return{type:VALUE_TYPES.BINARY,value:ascii85.encode(val)}}else if(typeof val==="object"){console.assert(Object.keys(val).length===0,"child object stored in parent can only be empty");return val}};const unprocessed=`Caller should have pre-processed the value by converting it to a string`;if(node.type===VALUE_TYPES.ARRAY&&node.value instanceof Array){console.warn(`Unprocessed array. ${unprocessed}`);const obj={};for(let i=0;i{node.value[key]=getTypedChildValue(original[key])})}return options.transaction.set(path,node)}_processReadNodeValue(node){const getTypedChildValue=val=>{if(val.type===VALUE_TYPES.BINARY){return ascii85.decode(val.value)}else if(val.type===VALUE_TYPES.DATETIME){return new Date(val.value)}else if(val.type===VALUE_TYPES.REFERENCE){return new PathReference(val.value)}else{throw new Error(`Unhandled child value type ${val.type}`)}};switch(node.type){case VALUE_TYPES.ARRAY:case VALUE_TYPES.OBJECT:{const obj=node.value;Object.keys(obj).forEach(key=>{let item=obj[key];if(typeof item==="object"&&"type"in item){obj[key]=getTypedChildValue(item)}});node.value=obj;break}case VALUE_TYPES.BINARY:{node.value=ascii85.decode(node.value);break}case VALUE_TYPES.REFERENCE:{node.value=new PathReference(node.value);break}case VALUE_TYPES.STRING:{break}default:throw new Error(`Invalid standalone record value type`)}}async _readNode(path,options){let node=await options.transaction.get(path);if(node===null){return null}if(typeof node!=="object"){throw new Error(`CustomStorage get function must return an ICustomStorageNode object. Use JSON.parse if your set function stored it as a string`)}this._processReadNodeValue(node);return node}_getTypeFromStoredValue(val){let type;if(typeof val==="string"){type=VALUE_TYPES.STRING}else if(typeof val==="number"){type=VALUE_TYPES.NUMBER}else if(typeof val==="boolean"){type=VALUE_TYPES.BOOLEAN}else if(val instanceof Array){type=VALUE_TYPES.ARRAY}else if(typeof val==="object"){if("type"in val){type=val.type;val=val.value;if(type===VALUE_TYPES.DATETIME){val=new Date(val)}else if(type===VALUE_TYPES.REFERENCE){val=new PathReference(val)}}else{type=VALUE_TYPES.OBJECT}}else{throw new Error(`Unknown value type`)}return{type:type,value:val}}async _writeNode(path,value,options){if(this.valueFitsInline(value)&&path!==""){throw new Error(`invalid value to store in its own node`)}else if(path===""&&(typeof value!=="object"||value instanceof Array)){throw new Error(`Invalid root node value. Must be an object`)}const transaction=options.transaction;const currentRow=await this._readNode(path,{transaction:transaction});if(options.merge&¤tRow){if(currentRow.type===VALUE_TYPES.ARRAY&&!(value instanceof Array)&&typeof value==="object"&&Object.keys(value).some(key=>isNaN(key))){throw new Error(`Cannot merge existing array of path "${path}" with an object`)}if(value instanceof Array&¤tRow.type!==VALUE_TYPES.ARRAY){throw new Error(`Cannot merge existing object of path "${path}" with an array`)}}const revision=options.revision||ID.generate();let mainNode={type:currentRow&¤tRow.type===VALUE_TYPES.ARRAY?VALUE_TYPES.ARRAY:VALUE_TYPES.OBJECT,value:{}};const childNodeValues={};if(value instanceof Array){mainNode.type=VALUE_TYPES.ARRAY;const obj={};for(let i=0;i{const val=value[key];delete mainNode.value[key];if(val===null){return}else if(typeof val==="undefined"){if(this.settings.removeVoidProperties===true){delete value[key];return}else{throw new Error(`Property "${key}" has invalid value. Cannot store undefined values. Set removeVoidProperties option to true to automatically remove undefined properties`)}}if(this.valueFitsInline(val)){mainNode.value[key]=val}else{childNodeValues[key]=val}})}const isArray=mainNode.type===VALUE_TYPES.ARRAY;if(currentRow){this.debug.log(`Node "/${path}" is being ${options.merge?"updated":"overwritten"}`.cyan);if(currentIsObjectOrArray||newIsObjectOrArray){const pathInfo=PathInfo.get(path);const keys=[];let checkExecuted=false;const includeChildCheck=childPath=>{checkExecuted=true;if(!pathInfo.isParentOf(childPath)){throw new Error(`"${childPath}" is not a child of "${path}" - childrenOf must only check and return paths that are children`)}return true};const addChildPath=childPath=>{if(!checkExecuted){throw new Error(`${this._customImplementation.info} childrenOf did not call checkCallback before addCallback`)}const key=PathInfo.get(childPath).key;keys.push(key.toString());return true};await transaction.childrenOf(path,{metadata:false,value:false},includeChildCheck,addChildPath);children.current=children.current.concat(keys);if(newIsObjectOrArray){if(options&&options.merge){children.new=children.current.slice()}Object.keys(value).forEach(key=>{if(!children.new.includes(key)){children.new.push(key)}})}const changes={insert:children.new.filter(key=>!children.current.includes(key)),update:[],delete:options&&options.merge?Object.keys(value).filter(key=>value[key]===null):children.current.filter(key=>!children.new.includes(key))};changes.update=children.new.filter(key=>children.current.includes(key)&&!changes.delete.includes(key));if(isArray&&options.merge&&(changes.insert.length>0||changes.delete.length>0)){const newArrayKeys=changes.update.concat(changes.insert);const isExhaustive=newArrayKeys.every((k,index,arr)=>arr.includes(index.toString()));if(!isExhaustive){throw new Error(`Elements cannot be inserted beyond, or removed before the end of an array. Rewrite the whole array at path "${path}" or change your schema to use an object collection instead`)}}const writePromises=Object.keys(childNodeValues).map(key=>{if(isArray){key=parseInt(key)}const childPath=pathInfo.childPath(key);const childValue=childNodeValues[key];return this._writeNode(childPath,childValue,{transaction:transaction,revision:revision,merge:false})});const movingNodes=keys.filter(key=>key in mainNode.value);const deleteDedicatedKeys=changes.delete.concat(movingNodes);const deletePromises=deleteDedicatedKeys.map(key=>{if(isArray){key=parseInt(key)}const childPath=pathInfo.childPath(key);return this._deleteNode(childPath,{transaction:transaction})});const promises=writePromises.concat(deletePromises);await Promise.all(promises)}return await this._storeNode(path,{type:mainNode.type,value:mainNode.value,revision:currentRow.revision,revision_nr:currentRow.revision_nr+1,created:currentRow.created,modified:Date.now()},{transaction:transaction})}else{this.debug.log(`Node "/${path}" is being created`.cyan);if(isArray){const arrayKeys=Object.keys(mainNode.value).concat(Object.keys(childNodeValues));const isExhaustive=arrayKeys.every((k,index,arr)=>arr.includes(index.toString()));if(!isExhaustive){throw new Error(`Cannot store arrays with missing entries`)}}const promises=Object.keys(childNodeValues).map(key=>{if(isArray){key=parseInt(key)}const childPath=PathInfo.getChildPath(path,key);const childValue=childNodeValues[key];return this._writeNode(childPath,childValue,{transaction:transaction,revision:revision,merge:false})});const p=this._storeNode(path,{type:mainNode.type,value:mainNode.value,revision:revision,revision_nr:1,created:Date.now(),modified:Date.now()},{transaction:transaction});promises.push(p);return Promise.all(promises)}}async _deleteNode(path,options){const pathInfo=PathInfo.get(path);this.debug.log(`Node "/${path}" is being deleted`.cyan);const deletePaths=[path];let checkExecuted=false;const includeDescendantCheck=descPath=>{checkExecuted=true;if(!pathInfo.isAncestorOf(descPath)){throw new Error(`"${descPath}" is not a descendant of "${path}" - descendantsOf must only check and return paths that are descendants`)}return true};const addDescendant=descPath=>{if(!checkExecuted){throw new Error(`${this._customImplementation.info} descendantsOf did not call checkCallback before addCallback`)}deletePaths.push(descPath);return true};const transaction=options.transaction;await transaction.descendantsOf(path,{metadata:false,value:false},includeDescendantCheck,addDescendant);this.debug.log(`Nodes ${deletePaths.map(p=>`"/${p}"`).join(",")} are being deleted`.cyan);return transaction.removeMultiple(deletePaths)}getChildren(path,options){options=options||{};var callback;const generator={next(valueCallback){callback=valueCallback;return start()}};const start=async()=>{const transaction=options.transaction||await this._customImplementation.getTransaction({path:path,write:false});try{let canceled=false;await(async()=>{let node=await this._readNode(path,{transaction:transaction});if(!node){throw new NodeNotFoundError(`Node "/${path}" does not exist`)}if(![VALUE_TYPES.OBJECT,VALUE_TYPES.ARRAY].includes(node.type)){return}const isArray=node.type===VALUE_TYPES.ARRAY;const value=node.value;let keys=Object.keys(value);if(options.keyFilter){keys=keys.filter(key=>options.keyFilter.includes(key))}const pathInfo=PathInfo.get(path);keys.length>0&&keys.every(key=>{let child=this._getTypeFromStoredValue(value[key]);const info=new CustomStorageNodeInfo({path:pathInfo.childPath(key),key:isArray?null:key,index:isArray?key:null,type:child.type,address:null,exists:true,value:child.value,revision:node.revision,revision_nr:node.revision_nr,created:node.created,modified:node.modified});canceled=callback(info)===false;return!canceled});if(canceled){return}let checkExecuted=false;const includeChildCheck=childPath=>{checkExecuted=true;if(!pathInfo.isParentOf(childPath)){throw new Error(`"${childPath}" is not a child of "${path}" - childrenOf must only check and return paths that are children`)}if(options.keyFilter){const key=PathInfo.get(childPath).key;return options.keyFilter.includes(key)}return true};const addChildNode=(childPath,node)=>{if(!checkExecuted){throw new Error(`${this._customImplementation.info} childrenOf did not call checkCallback before addCallback`)}const key=PathInfo.get(childPath).key;const info=new CustomStorageNodeInfo({path:childPath,type:node.type,key:isArray?null:key,index:isArray?key:null,address:new CustomStorageNodeAddress(childPath),exists:true,value:null,revision:node.revision,revision_nr:node.revision_nr,created:new Date(node.created),modified:new Date(node.modified)});canceled=callback(info)===false;return!canceled};await transaction.childrenOf(path,{metadata:true,value:false},includeChildCheck,addChildNode)})();if(!options.transaction){await transaction.commit()}return canceled}catch(err){if(!options.transaction){await transaction.rollback(err)}throw err}};return generator}async getNode(path,options){options=options||{};const transaction=options.transaction||await this._customImplementation.getTransaction({path:path,write:false});try{const node=await(async()=>{const filtered=options.include||options.exclude||options.child_objects===false;const pathInfo=PathInfo.get(path);const targetNode=await this._readNode(path,{transaction:transaction});if(!targetNode){if(path===""){return{value:null}}const lockPath=await transaction.moveToParentPath(pathInfo.parentPath);console.assert(lockPath===pathInfo.parentPath,`transaction.moveToParentPath() did not move to the right parent path of "${path}"`);let parentNode=await this._readNode(pathInfo.parentPath,{transaction:transaction});if(parentNode&&[VALUE_TYPES.OBJECT,VALUE_TYPES.ARRAY].includes(parentNode.type)&&pathInfo.key in parentNode){const childValueInfo=this._getTypeFromStoredValue(parentNode.value[pathInfo.key]);return{revision:parentNode.revision,revision_nr:parentNode.revision_nr,created:parentNode.created,modified:parentNode.modified,type:childValueInfo.type,value:childValueInfo.value}}return{value:null}}const includeCheck=options.include?new RegExp("^"+options.include.map(p=>"(?:"+p.replace(/\*/g,"[^/\\[]+")+")").join("|")+"(?:$|[/\\[])"):null;const excludeCheck=options.exclude?new RegExp("^"+options.exclude.map(p=>"(?:"+p.replace(/\*/g,"[^/\\[]+")+")").join("|")+"(?:$|[/\\[])"):null;let checkExecuted=false;const includeDescendantCheck=descPath=>{checkExecuted=true;if(!pathInfo.isAncestorOf(descPath)){throw new Error(`"${descPath}" is not a descendant of "${path}" - descendantsOf must only check and return paths that are descendants`)}if(!filtered){return true}let checkPath=descPath.slice(path.length);if(checkPath[0]==="/"){checkPath=checkPath.slice(1)}let include=(includeCheck?includeCheck.test(checkPath):true)&&(excludeCheck?!excludeCheck.test(checkPath):true);if(include&&options.child_objects===false&&(pathInfo.isParentOf(descPath)&&[VALUE_TYPES.OBJECT,VALUE_TYPES.ARRAY].includes(childNode.type)||PathInfo.getPathKeys(descPath).length>pathInfo.pathKeys.length+1)){include=false}return include};const descRows=[];const addDescendant=(descPath,node)=>{if(!checkExecuted){throw new Error(`${this._customImplementation.info} descendantsOf did not call checkCallback before addCallback`)}this._processReadNodeValue(node);node.path=descPath;descRows.push(node);return true};await transaction.descendantsOf(path,{metadata:true,value:true},includeDescendantCheck,addDescendant);this.debug.log(`Read node "/${path}" and ${filtered?"(filtered) ":""}descendants from ${descRows.length+1} records`.magenta);const result=targetNode;const objectToArray=obj=>{const arr=[];Object.keys(obj).forEach(key=>{let index=parseInt(key);arr[index]=obj[index]});return arr};if(targetNode.type===VALUE_TYPES.ARRAY){result.value=objectToArray(result.value)}if(targetNode.type===VALUE_TYPES.OBJECT||targetNode.type===VALUE_TYPES.ARRAY){const targetPathKeys=PathInfo.getPathKeys(path);let value=targetNode.value;for(let i=0;i{console.assert(!(childKey in parent[key]),"child key is in parent value already?! HOW?!");parent[key][childKey]=nodeValue[childKey]})}else{parent[key]=nodeValue}parent=parent[key]}}}else if(descRows.length>0){throw new Error(`multiple records found for non-object value!`)}if(options.child_objects===false){Object.keys(result.value).forEach(key=>{if(typeof result.value[key]==="object"&&result.value[key].constructor===Object){console.assert(Object.keys(result.value[key]).length===0);delete result.value[key]}})}if(options.exclude){const process=(obj,keys)=>{if(typeof obj!=="object"){return}const key=keys[0];if(key==="*"){Object.keys(obj).forEach(k=>{process(obj[k],keys.slice(1))})}else if(keys.length>1){key in obj&&process(obj[key],keys.slice(1))}else{delete obj[key]}};options.exclude.forEach(path=>{const checkKeys=PathInfo.getPathKeys(path);process(result.value,checkKeys)})}return result})();if(!options.transaction){await transaction.commit()}return node}catch(err){if(!options.transaction){await transaction.rollback(err)}throw err}}async getNodeInfo(path,options){options=options||{};const pathInfo=PathInfo.get(path);const transaction=options.transaction||await this._customImplementation.getTransaction({path:path,write:true});try{const node=await this._readNode(path,{transaction:transaction});const info=new CustomStorageNodeInfo({path:path,key:typeof pathInfo.key==="string"?pathInfo.key:null,index:typeof pathInfo.key==="number"?pathInfo.key:null,type:node?node.type:0,exists:node!==null,address:node?new CustomStorageNodeAddress(path):null,created:node?new Date(node.created):null,modified:node?new Date(node.modified):null,revision:node?node.revision:null,revision_nr:node?node.revision_nr:null});if(!node&&path!==""){const lockPath=await transaction.moveToParentPath(pathInfo.parentPath);console.assert(lockPath===pathInfo.parentPath,`transaction.moveToParentPath() did not move to the right parent path of "${path}"`);const parent=await this._readNode(pathInfo.parentPath,{transaction:transaction});if(parent&&[VALUE_TYPES.OBJECT,VALUE_TYPES.ARRAY].includes(parent.type)&&pathInfo.key in parent.value){info.exists=true;info.value=parent.value[pathInfo.key];info.address=null;info.type=parent.type;info.created=new Date(parent.created);info.modified=new Date(parent.modified);info.revision=parent.revision;info.revision_nr=parent.revision_nr}else{info.address=null}}if(!options.transaction){await transaction.commit()}return info}catch(err){if(!options.transaction){await transaction.rollback(err)}throw err}}async removeNode(path,options){if(path===""){return Promise.reject(new Error(`Cannot remove the root node`))}options=options||{};const pathInfo=PathInfo.get(path);const transaction=options.transaction||this._customImplementation.getTransaction({path:path,write:true});try{await this.updateNode(pathInfo.parentPath,{[pathInfo.key]:null},{transaction:transaction});if(!options.transaction){await transaction.commit()}}catch(err){if(!options.transaction){await transaction.rollback(err)}throw err}}async setNode(path,value,options){const pathInfo=PathInfo.get(path);options=options||{};const transaction=options.transaction||await this._customImplementation.getTransaction({path:path,write:true});try{if(path===""){if(value===null||typeof value!=="object"||value instanceof Array||value instanceof ArrayBuffer||"buffer"in value&&value.buffer instanceof ArrayBuffer){throw new Error(`Invalid value for root node: ${value}`)}await this._writeNodeWithTracking("",value,{merge:false,transaction:transaction})}else if(typeof options.assert_revision!=="undefined"){const info=await this.getNodeInfo(path,{transaction:transaction});if(info.revision!==options.assert_revision){throw new NodeRevisionError(`revision '${info.revision}' does not match requested revision '${options.assert_revision}'`)}if(info.address&&info.address.path===path&&!this.valueFitsInline(value)){await this._writeNodeWithTracking(path,value,{merge:false,transaction:transaction})}else{const lockPath=await transaction.moveToParentPath(pathInfo.parentPath);console.assert(lockPath===pathInfo.parentPath,`transaction.moveToParentPath() did not move to the right parent path of "${path}"`);await this._writeNodeWithTracking(pathInfo.parentPath,{[pathInfo.key]:value},{merge:true,transaction:transaction})}}else{const lockPath=await transaction.moveToParentPath(pathInfo.parentPath);console.assert(lockPath===pathInfo.parentPath,`transaction.moveToParentPath() did not move to the right parent path of "${path}"`);await this.updateNode(pathInfo.parentPath,{[pathInfo.key]:value},{transaction:transaction})}if(!options.transaction){await transaction.commit()}}catch(err){if(!options.transaction){await transaction.rollback(err)}throw err}}async updateNode(path,updates,options){if(typeof updates!=="object"){throw new Error(`invalid updates argument`)}options=options||{};const transaction=options.transaction||await this._customImplementation.getTransaction({path:path,write:true});try{const nodeInfo=await this.getNodeInfo(path,{transaction:transaction});const pathInfo=PathInfo.get(path);if(nodeInfo.exists&&nodeInfo.address&&nodeInfo.address.path===path){await this._writeNodeWithTracking(path,updates,{transaction:transaction,merge:true})}else if(nodeInfo.exists){const pathInfo=PathInfo.get(path);const lockPath=await transaction.moveToParentPath(pathInfo.parentPath);console.assert(lockPath===pathInfo.parentPath,`transaction.moveToParentPath() did not move to the right parent path of "${path}"`);await this._writeNodeWithTracking(pathInfo.parentPath,{[pathInfo.key]:updates},{transaction:transaction,merge:true})}else{const lockPath=await transaction.moveToParentPath(pathInfo.parentPath);console.assert(lockPath===pathInfo.parentPath,`transaction.moveToParentPath() did not move to the right parent path of "${path}"`);await this.updateNode(pathInfo.parentPath,{[pathInfo.key]:updates},{transaction:transaction})}if(!options.transaction){await transaction.commit()}}catch(err){if(!options.transaction){await transaction.rollback(err)}throw err}}}module.exports={CustomStorageNodeAddress:CustomStorageNodeAddress,CustomStorageNodeInfo:CustomStorageNodeInfo,CustomStorage:CustomStorage,CustomStorageSettings:CustomStorageSettings,CustomStorageHelpers:CustomStorageHelpers,CustomStorageTransaction:CustomStorageTransaction,ICustomStorageNodeMetaData:ICustomStorageNodeMetaData,ICustomStorageNode:ICustomStorageNode}},{"./node-info":34,"./node-lock":35,"./node-value-types":36,"./storage":39,"acebase-core":11}],39:[function(require,module,exports){(function(process){const{Utils:Utils,DebugLogger:DebugLogger,PathInfo:PathInfo,ID:ID,PathReference:PathReference,ascii85:ascii85}=require("acebase-core");const{NodeLocker:NodeLocker}=require("./node-lock");const{VALUE_TYPES:VALUE_TYPES,getValueTypeName:getValueTypeName}=require("./node-value-types");const{NodeInfo:NodeInfo}=require("./node-info");const{EventEmitter:EventEmitter}=require("events");const{cloneObject:cloneObject,compareValues:compareValues,getChildValues:getChildValues,encodeString:encodeString}=Utils;const colors=require("colors");class NodeNotFoundError extends Error{}class NodeRevisionError extends Error{}class ClusterSettings{constructor(settings){settings=settings||{};this.enabled=settings.enabled===true;this.isMaster=settings.isMaster===true;this.master=this.isMaster?null:settings.master;this.workers=this.isMaster?settings.workers:null}}class ClusterManager extends EventEmitter{constructor(settings){super();this.settings=new ClusterSettings(settings);if(!settings.enabled){}else if(settings.isMaster){settings.workers.forEach(worker=>{worker.on("message",data=>{const{id:id,request:request}=data;if(typeof request==="object"&&request.type==="ping"){worker.send({id:id,result:"pong"})}else{const reply=result=>{worker.send({id:id,result:result})};const broadcast=msg=>{console.assert(!("id"in msg),"message to broadcast cannot have id property, it will confuse workers because they think it is a reply to their request");settings.workers.forEach(otherWorker=>{if(otherWorker!==worker){otherWorker.send(msg)}})};this.emit("worker_request",{request:request,reply:reply,broadcast:broadcast})}})});this.request=msg=>{throw new Error(`request can only be called by worker processes!`)}}else{const master=settings.master;const requests={};this.request=msg=>{return new Promise((resolve,reject)=>{const id=ID.generate();requests[id]=resolve;master.send({id:id,request:msg})})};master.on("message",data=>{if(typeof data.id!=="undefined"){let resolve=requests[data.id];delete requests[data.id];resolve(data.result)}else{this.emit("master_notification",data)}});this.request({type:"ping"}).then(result=>{console.log(`PING master process result: ${result}`)})}}get isMaster(){return this.settings.isMaster}get enabled(){return this.settings.enabled}}class StorageSettings{constructor(settings){settings=settings||{};this.maxInlineValueSize=typeof settings.maxInlineValueSize==="number"?settings.maxInlineValueSize:50;this.removeVoidProperties=settings.removeVoidProperties===true;this.cluster=new ClusterSettings(settings.cluster);this.path=settings.path||".";if(this.path.endsWith("/")){this.path=this.path.slice(0,-1)}this.logLevel=settings.logLevel||"log";this.info=settings.info||"realtime database"}}class Storage extends EventEmitter{constructor(name,settings){super();this.name=name;this.settings=settings;this.debug=new DebugLogger(settings.logLevel,`[${name}]`);colors.setTheme({art:["magenta","bold"],intro:["dim"]});const logo=" ___ ______ ".art+"\n"+" / _ \\ | ___ \\ ".art+"\n"+" / /_\\ \\ ___ ___| |_/ / __ _ ___ ___ ".art+"\n"+" | _ |/ __/ _ \\ ___ \\/ _` / __|/ _ \\".art+"\n"+" | | | | (_| __/ |_/ / (_| \\__ \\ __/".art+"\n"+" \\_| |_/\\___\\___\\____/ \\__,_|___/\\___|".art+"\n"+(settings.info?"".padStart(40-settings.info.length," ")+settings.info.magenta+"\n":"");this.debug.write(logo);this.nodeCache={find(path){return null},update(path,info){}};this.nodeLocker=new NodeLocker;this.cluster=new ClusterManager(settings.cluster);const{DataIndex:DataIndex,ArrayIndex:ArrayIndex,FullTextIndex:FullTextIndex,GeoIndex:GeoIndex}=require("./data-index");const _indexes=[];const storage=this;this.indexes={get supported(){const pfs=require("./promise-fs");return pfs&&pfs.hasFileSystem},create(path,key,options={rebuild:false,type:undefined,include:undefined}){path=path.replace(/\/\*$/,"");const rebuild=options&&options.rebuild===true;const indexType=options&&options.type||"normal";let includeKeys=options&&options.include||[];if(typeof includeKeys==="string"){includeKeys=[includeKeys]}const existingIndex=_indexes.find(index=>index.path===path&&index.key===key&&index.type===indexType&&index.includeKeys.length===includeKeys.length&&index.includeKeys.every((key,index)=>includeKeys[index]===key));if(existingIndex&&rebuild!==true){storage.debug.log(`Index on "/${path}/*/${key}" already exists`.inverse);return Promise.resolve(existingIndex)}const index=existingIndex||(()=>{switch(indexType){case"array":return new ArrayIndex(storage,path,key,{include:options.include,config:options.config});case"fulltext":return new FullTextIndex(storage,path,key,{include:options.include,config:options.config});case"geo":return new GeoIndex(storage,path,key,{include:options.include,config:options.config});default:return new DataIndex(storage,path,key,{include:options.include,config:options.config})}})();if(!existingIndex){_indexes.push(index)}return index.build().then(()=>{return index}).catch(err=>{storage.debug.error(`Index build on "/${path}/*/${key}" failed: ${err.message} (code: ${err.code})`.red);if(!existingIndex){_indexes.splice(_indexes.indexOf(index),1)}throw err})},get(path,key=null){const matchesNamedWildcardPath=index=>{if(!index.path.includes("$")){return false}const pattern="^"+index.path.replace(/\$[a-z0-9_]+/gi,"[a-z0-9_]+|\\*")+"$";const re=new RegExp(pattern,"i");return re.test(path)};return _indexes.filter(index=>(index.path===path||matchesNamedWildcardPath(index))&&(key===null||key===index.key))},getAll(targetPath,options={parentPaths:true,childPaths:true}){const pathKeys=PathInfo.getPathKeys(targetPath);return _indexes.filter(index=>{const indexKeys=PathInfo.getPathKeys(index.path+"/*");if(options.parentPaths&&indexKeys.every((key,i)=>{return key==="*"||pathKeys[i]===key})&&[index.key].concat(...index.includeKeys).includes(pathKeys[indexKeys.length])){return true}else if(indexKeys.length{return[key,"*"].includes(indexKeys[i])})})},list(){return _indexes.slice()},load(){_indexes.splice(0);const pfs=require("./promise-fs");if(!pfs||!pfs.readdir){return Promise.resolve()}return pfs.readdir(`${storage.settings.path}/${storage.name}.acebase`).then(files=>{const promises=[];files.forEach(fileName=>{if(fileName.endsWith(".idx")){const p=DataIndex.readFromFile(storage,fileName).then(index=>{_indexes.push(index)}).catch(err=>{storage.debug.error(err)});promises.push(p)}});return Promise.all(promises)}).catch(err=>{if(err.code!=="ENOENT"){storage.debug.error(err)}})}};const _subs={};const _supportedEvents=["value","child_added","child_changed","child_removed"];_supportedEvents.push(..._supportedEvents.map(event=>`notify_${event}`));this.subscriptions={add(path,type,callback){if(_supportedEvents.indexOf(type)<0){throw new TypeError(`Invalid event type "${type}"`)}let pathSubs=_subs[path];if(!pathSubs){pathSubs=_subs[path]=[]}pathSubs.push({created:Date.now(),type:type,callback:callback})},remove(path,type=undefined,callback=undefined){let pathSubs=_subs[path];if(!pathSubs){return}while(true){const i=pathSubs.findIndex(ps=>(type?ps.type===type:true)&&(callback?ps.callback===callback:true));if(i<0){break}pathSubs.splice(i,1)}},hasValueSubscribersForPath(path){const valueNeeded=this.getValueSubscribersForPath(path);return!!valueNeeded},getValueSubscribersForPath(path){const pathInfo=new PathInfo(path);const valueSubscribers=[];Object.keys(_subs).forEach(subscriptionPath=>{if(pathInfo.equals(subscriptionPath)||pathInfo.isDescendantOf(subscriptionPath)){let pathSubs=_subs[subscriptionPath];const eventPath=PathInfo.fillVariables(subscriptionPath,path);pathSubs.forEach(sub=>{let dataPath=null;if(sub.type==="value"||sub.type==="notify_value"){dataPath=eventPath}else if((sub.type==="child_changed"||sub.type==="notify_child_changed")&&path!==eventPath){let childKey=PathInfo.getPathKeys(path.slice(eventPath.length).replace(/^\//,""))[0];dataPath=PathInfo.getChildPath(eventPath,childKey)}else if(["child_added","child_removed","notify_child_added","notify_child_removed"].includes(sub.type)&&pathInfo.isChildOf(eventPath)){let childKey=PathInfo.getPathKeys(path.slice(eventPath.length).replace(/^\//,""))[0];dataPath=PathInfo.getChildPath(eventPath,childKey)}if(dataPath!==null&&valueSubscribers.findIndex(s=>s.type===sub.type&&s.path===eventPath)<0){valueSubscribers.push({type:sub.type,eventPath:eventPath,dataPath:dataPath,subscriptionPath:subscriptionPath})}})}});return valueSubscribers},getAllSubscribersForPath(path){const pathInfo=PathInfo.get(path);const subscribers=[];Object.keys(_subs).forEach(subscriptionPath=>{if(pathInfo.equals(subscriptionPath)||pathInfo.isDescendantOf(subscriptionPath)||pathInfo.isAncestorOf(subscriptionPath)){let pathSubs=_subs[subscriptionPath];const eventPath=PathInfo.fillVariables(subscriptionPath,path);pathSubs.forEach(sub=>{let dataPath=null;if(sub.type==="value"||sub.type==="notify_value"){dataPath=eventPath}else if(sub.type==="child_changed"||sub.type==="notify_child_changed"){let childKey=path===eventPath||pathInfo.isAncestorOf(eventPath)?"*":PathInfo.getPathKeys(path.slice(eventPath.length).replace(/^\//,""))[0];dataPath=PathInfo.getChildPath(eventPath,childKey)}else if(["child_added","child_removed","notify_child_added","notify_child_removed"].includes(sub.type)&&(pathInfo.isChildOf(eventPath)||path===eventPath||pathInfo.isAncestorOf(eventPath))){let childKey=path===eventPath||pathInfo.isAncestorOf(eventPath)?"*":PathInfo.getPathKeys(path.slice(eventPath.length).replace(/^\//,""))[0];dataPath=PathInfo.getChildPath(eventPath,childKey)}if(dataPath!==null&&!subscribers.some(s=>s.type===sub.type&&s.eventPath===eventPath)){subscribers.push({type:sub.type,eventPath:eventPath,dataPath:dataPath,subscriptionPath:subscriptionPath})}})}});return subscribers},trigger(event,path,dataPath,oldValue,newValue){const pathSubscriptions=_subs[path]||[];pathSubscriptions.filter(sub=>sub.type===event).forEach(sub=>{sub.callback(null,dataPath,newValue,oldValue)})}}}get path(){return`${this.settings.path}/${this.name}.acebase`}valueFitsInline(value){const encoding="utf8";if(typeof value==="number"||typeof value==="boolean"||value instanceof Date){return true}else if(typeof value==="string"){if(value.length>this.settings.maxInlineValueSize){return false}const encoded=encodeString(value);return encoded.lengththis.settings.maxInlineValueSize){return false}const encoded=encodeString(value.path);return encoded.length0){hasValueSubscribers=true;let eventPaths=valueSubscribers.map(sub=>{return{path:sub.dataPath,keys:PathInfo.getPathKeys(sub.dataPath)}}).sort((a,b)=>{if(a.keys.lengthb.keys.length)return 1;return 0});let first=eventPaths[0];topEventPath=first.path;if(valueSubscribers.filter(sub=>sub.dataPath===topEventPath).every(sub=>sub.type.startsWith("notify_"))){hasValueSubscribers=false}topEventPath=PathInfo.fillVariables(topEventPath,path)}const writeNode=()=>{if(typeof options._customWriteFunction==="function"){return options._customWriteFunction()}return this._writeNode(path,value,options)};const indexes=this.indexes.getAll(path,{childPaths:true,parentPaths:true}).map(index=>({index:index,keys:PathInfo.getPathKeys(index.path)})).sort((a,b)=>{if(a.keys.lengthb.keys.length){return 1}return 0}).map(obj=>obj.index);if(eventSubscriptions.length===0&&indexes.length===0){return writeNode()}let keysFilter=[];if(indexes.length>0){indexes.sort((a,b)=>{if(typeof a._pathKeys==="undefined"){a._pathKeys=PathInfo.getPathKeys(a.path)}if(typeof b._pathKeys==="undefined"){b._pathKeys=PathInfo.getPathKeys(b.path)}if(a._pathKeys.lengthb._pathKeys.length)return 1;return 0});const topIndex=indexes[0];let topIndexPath=topIndex.path===path?path:PathInfo.fillVariables(`${topIndex.path}/*`,path);if(topIndexPath.lengthindex.path===topIndex.path).forEach(index=>{let keys=[index.key].concat(index.includeKeys);keys.forEach(key=>!keysFilter.includes(key)&&keysFilter.push(key))})}}if(!hasValueSubscribers&&options.merge===true&&keysFilter.length===0){keysFilter=Object.keys(value);if(topEventPath!==path){let trailPath=path.slice(topEventPath.length);keysFilter=keysFilter.map(key=>`${trailPath}/${key}`)}}return this.getNodeInfo(topEventPath,{transaction:transaction,tid:tid}).then(eventNodeInfo=>{if(!eventNodeInfo.exists){return null}let valueOptions={transaction:transaction,tid:tid};if(keysFilter.length>0){valueOptions.include=keysFilter}if(topEventPath===""&&typeof valueOptions.include==="undefined"){this.debug.warn(`WARNING: One or more value event listeners on the root node are causing the entire database value to be read to facilitate change tracking. Using "value", "notify_value", "child_changed" and "notify_child_changed" events on the root node are a bad practice because of the significant performance impact`)}return this.getNodeValue(topEventPath,valueOptions)}).then(currentValue=>{topEventData=currentValue;return writeNode()}).then(result=>{let newTopEventData=cloneObject(topEventData);if(newTopEventData===null){newTopEventData=path===topEventPath?value:{}}let modifiedData=newTopEventData;if(path!==topEventPath){let trailPath=path.slice(topEventPath.length).replace(/^\//,"");let trailKeys=PathInfo.getPathKeys(trailPath);while(trailKeys.length>0){let childKey=trailKeys.shift();if(!options.merge&&trailKeys.length===0){modifiedData[childKey]=value}else{if(!(childKey in modifiedData)){modifiedData[childKey]={}}modifiedData=modifiedData[childKey]}}}if(options.merge){Object.keys(value).forEach(key=>{let newValue=value[key];if(newValue!==null){modifiedData[key]=newValue}else{delete modifiedData[key]}})}else if(path===topEventPath){newTopEventData=modifiedData=value}const indexUpdates=[];indexes.map(index=>({index:index,keys:PathInfo.getPathKeys(index.path)})).sort((a,b)=>{if(a.keys.lengthb.keys.length){return-1}return 0}).forEach(({index:index})=>{let pathKeys=PathInfo.getPathKeys(topEventPath);let indexPathKeys=PathInfo.getPathKeys(index.path+"/*");let trailKeys=indexPathKeys.slice(pathKeys.length);let oldValue=topEventData;let newValue=newTopEventData;if(trailKeys.length===0){console.assert(pathKeys.length===indexPathKeys.length,"check logic");const p=index.handleRecordUpdate(topEventPath,oldValue,newValue);indexUpdates.push(p);return}const getAllIndexUpdates=(path,oldValue,newValue)=>{if(oldValue===null&&newValue===null){return[]}let pathKeys=PathInfo.getPathKeys(path);let indexPathKeys=PathInfo.getPathKeys(index.path+"/*");let trailKeys=indexPathKeys.slice(pathKeys.length);if(trailKeys.length===0){console.assert(pathKeys.length===indexPathKeys.length,"check logic");return[{path:path,oldValue:oldValue,newValue:newValue}]}let results=[];let trailPath="";while(trailKeys.length>0){let subKey=trailKeys.shift();if(subKey==="*"){let allKeys=oldValue===null?[]:Object.keys(oldValue);newValue!==null&&Object.keys(newValue).forEach(key=>{if(allKeys.indexOf(key)<0){allKeys.push(key)}});allKeys.forEach(key=>{let childPath=PathInfo.getChildPath(trailPath,key);let childValues=getChildValues(key,oldValue,newValue);let subTrailPath=PathInfo.getChildPath(path,childPath);let childResults=getAllIndexUpdates(subTrailPath,childValues.oldValue,childValues.newValue);results=results.concat(childResults)});break}else{let values=getChildValues(subKey,oldValue,newValue);oldValue=values.oldValue;newValue=values.newValue;if(oldValue===null&&newValue===null){break}trailPath=PathInfo.getChildPath(trailPath,subKey)}}return results};let results=getAllIndexUpdates(topEventPath,oldValue,newValue);results.forEach(result=>{const p=index.handleRecordUpdate(result.path,result.oldValue,result.newValue);indexUpdates.push(p)})});const callSubscriberWithValues=(sub,oldValue,newValue,variables=[])=>{let trigger=true;let type=sub.type;if(type.startsWith("notify_")){type=type.slice("notify_".length)}if(type==="child_changed"&&(oldValue===null||newValue===null)){trigger=false}else if(type==="value"||type==="child_changed"){let changes=compareValues(oldValue,newValue);trigger=changes!=="identical"}else if(type==="child_added"){trigger=oldValue===null&&newValue!==null}else if(type==="child_removed"){trigger=oldValue!==null&&newValue===null}let dataPath=sub.dataPath;variables.forEach((variable,i)=>{const safeVarName=variable.name==="*"?"\\*":variable.name.replace("$","\\$");dataPath=dataPath.replace(new RegExp(`(^|/)${safeVarName}([/[]|$)`),`$1${variable.value}$2`)});trigger&&this.subscriptions.trigger(sub.type,sub.subscriptionPath,dataPath,oldValue,newValue)};const triggerAllEvents=()=>{eventSubscriptions.map(sub=>{const keys=PathInfo.getPathKeys(sub.dataPath);return{sub:sub,keys:keys}}).sort((a,b)=>{if(a.keys.lengthb.keys.length){return-1}return 0}).forEach(({sub:sub})=>{const process=(currentPath,oldValue,newValue,variables=[])=>{let trailPath=sub.dataPath.slice(currentPath.length).replace(/^\//,"");let trailKeys=PathInfo.getPathKeys(trailPath);while(trailKeys.length>0){let subKey=trailKeys.shift();if(typeof subKey==="string"&&(subKey==="*"||subKey[0]==="$")){let allKeys=oldValue===null?[]:Object.keys(oldValue);newValue!==null&&Object.keys(newValue).forEach(key=>{if(allKeys.indexOf(key)<0){allKeys.push(key)}});allKeys.forEach(key=>{const childValues=getChildValues(key,oldValue,newValue);const vars=variables.concat({name:subKey,value:key});if(trailKeys.length===0){callSubscriberWithValues(sub,childValues.oldValue,childValues.newValue,vars)}else{process(`${currentPath}/${subKey}`,childValues.oldValue,childValues.newValue,vars)}});return}else{currentPath=PathInfo.getChildPath(currentPath,subKey);let childValues=getChildValues(subKey,oldValue,newValue);oldValue=childValues.oldValue;newValue=childValues.newValue}}callSubscriberWithValues(sub,oldValue,newValue,variables)};process(topEventPath,topEventData,newTopEventData)})};if(options.waitForIndexUpdates===false){indexUpdates.splice(0)}return Promise.all(indexUpdates).then(()=>{process.nextTick(triggerAllEvents);return result})})}getChildren(path,options={keyFilter:undefined,tid:undefined}){throw new Error(`This method must be implemented by subclass`)}getNodeValue(path,options={include:undefined,exclude:undefined,child_objects:true,tid:undefined}){return this.getNode(path,options).then(node=>{return node.value})}getNode(path,options={include:undefined,exclude:undefined,child_objects:true,tid:undefined}){throw new Error(`This method must be implemented by subclass`)}getNodeInfo(path,options={tid:undefined}){throw new Error(`This method must be implemented by subclass`)}removeNode(path,options={tid:undefined}){throw new Error(`This method must be implemented by subclass`)}setNode(path,value,options={tid:undefined}){throw new Error(`This method must be implemented by subclass`)}updateNode(path,updates,options={tid:undefined}){throw new Error(`This method must be implemented by subclass`)}transactNode(path,callback,options={no_lock:false}){let checkRevision;const tid=ID.generate();const lockPromise=options&&options.no_lock===true?Promise.resolve({tid:tid,release(){}}):this.nodeLocker.lock(path,tid,true,"transactNode");return lockPromise.then(lock=>{let changed=false,changeCallback=(err,path)=>{changed=true};if(options&&options.no_lock){this.subscriptions.add(path,"notify_value",changeCallback)}return this.getNode(path,{tid:tid}).then(node=>{checkRevision=node.revision;let newValue;try{newValue=callback(node.value)}catch(err){this.debug.error(`Error in transaction callback: ${err.message}`)}if(newValue instanceof Promise){return newValue.catch(err=>{this.debug.error(`Error in transaction callback: ${err.message}`)})}return newValue}).then(newValue=>{if(typeof newValue==="undefined"){return}if(options&&options.no_lock){this.subscriptions.remove(path,"notify_value",changeCallback)}if(changed){return Promise.reject(new NodeRevisionError(`Node changed`))}return this.setNode(path,newValue,{assert_revision:checkRevision,tid:lock.tid})}).then(result=>{lock.release();return result}).catch(err=>{lock.release();if(err instanceof NodeRevisionError){console.warn(`node value changed, running again. Error: ${err.message}`);return this.transactNode(path,callback,options)}else{throw err}})})}matchNode(path,criteria,options={tid:undefined}){const tid=options&&options.tid||ID.generate();const checkNode=(path,criteria)=>{if(criteria.length===0){return Promise.resolve(true)}const criteriaKeys=criteria.reduce((keys,cr)=>{if(keys.indexOf(cr.key)<0){keys.push(cr.key)}return keys},[]);const unseenKeys=criteriaKeys.slice();let isMatch=true;let delayedMatchPromises=[];return this.getChildren(path,{tid:tid,keyFilter:criteriaKeys}).next(childInfo=>{unseenKeys.includes(childInfo.key)&&unseenKeys.splice(unseenKeys.indexOf(childInfo.key),1);const keyCriteria=criteria.filter(cr=>cr.key===childInfo.key).map(cr=>({op:cr.op,compare:cr.compare}));const result=checkChild(childInfo,keyCriteria);isMatch=result.isMatch;delayedMatchPromises.push(...result.promises);if(!isMatch||unseenKeys.length===0){return false}}).then(()=>{if(isMatch){return Promise.all(delayedMatchPromises).then(results=>{isMatch=results.every(res=>res.isMatch)})}}).then(()=>{if(!isMatch){return false}isMatch=unseenKeys.every(key=>{const child=new NodeInfo({key:key,exists:false});const keyCriteria=criteria.filter(cr=>cr.key===key).map(cr=>({op:cr.op,compare:cr.compare}));const result=checkChild(child,keyCriteria);return result.isMatch});return isMatch}).catch(err=>{this.debug.error(`Error matching on "${path}": `,err);throw err})};const checkChild=(child,criteria)=>{const promises=[];const isMatch=criteria.every(f=>{let proceed=true;if(f.op==="!exists"||f.op==="=="&&(typeof f.compare==="undefined"||f.compare===null)){proceed=!child.exists}else if(f.op==="exists"||f.op==="!="&&(typeof f.compare==="undefined"||f.compare===null)){proceed=child.exists}else if(!child.exists){proceed=false}else{if(child.address){if(child.valueType===VALUE_TYPES.OBJECT&&["has","!has"].indexOf(f.op)>=0){const op=f.op==="has"?"exists":"!exists";const p=checkNode(child.path,[{key:f.compare,op:op}]).then(isMatch=>{return{key:child.key,isMatch:isMatch}});promises.push(p);proceed=true}else if(child.valueType===VALUE_TYPES.ARRAY&&["contains","!contains"].indexOf(f.op)>=0){const p=this.getNodeValue(child.path,{tid:tid}).then(arr=>{const isMatch=f.op==="contains"?f.compare instanceof Array?f.compare.every(val=>arr.includes(val)):arr.includes(f.compare):f.compare instanceof Array?!f.compare.some(val=>arr.includes(val)):!arr.includes(f.compare);return{key:child.key,isMatch:isMatch}});promises.push(p);proceed=true}else if(child.valueType===VALUE_TYPES.STRING){const p=this.getNodeValue(child.path,{tid:tid}).then(val=>{return{key:child.key,isMatch:this.test(val,f.op,f.compare)}});promises.push(p);proceed=true}else{proceed=false}}else if(child.type===VALUE_TYPES.OBJECT&&["has","!has"].indexOf(f.op)>=0){const has=f.compare in child.value;proceed=has&&f.op==="has"||!has&&f.op==="!has"}else if(child.type===VALUE_TYPES.ARRAY&&["contains","!contains"].indexOf(f.op)>=0){const contains=child.value.indexOf(f.compare)>=0;proceed=contains&&f.op==="contains"||!contains&&f.op==="!contains"}else{const ret=this.test(child.value,f.op,f.compare);if(ret instanceof Promise){promises.push(ret);ret=true}proceed=ret}}return proceed});return{isMatch:isMatch,promises:promises}};return checkNode(path,criteria)}test(val,op,compare){if(op==="<"){return val"){return val>compare}if(op===">="){return val>=compare}if(op==="in"){return compare.indexOf(val)>=0}if(op==="!in"){return compare.indexOf(val)<0}if(op==="like"||op==="!like"){const pattern="^"+compare.replace(/[-[\]{}()+.,\\^$|#\s]/g,"\\$&").replace(/\?/g,".").replace(/\*/g,".*?")+"$";const re=new RegExp(pattern,"i");const isMatch=re.test(val.toString());return op==="like"?isMatch:!isMatch}if(op==="matches"){return compare.test(val.toString())}if(op==="!matches"){return!compare.test(val.toString())}if(op==="between"){return val>=compare[0]&&val<=compare[1]}if(op==="!between"){return valcompare[1]}if(op==="has"||op==="!has"){const has=typeof val==="object"&&compare in val;return op==="has"?has:!has}if(op==="contains"||op==="!contains"){const includes=typeof val==="object"&&val instanceof Array&&val.includes(compare);return op==="contains"?includes:!includes}return false}exportNode(path,stream,options={format:"json"}){if(options&&options.format!=="json"){throw new Error(`Only json output is currently supported`)}const stringifyValue=(type,val)=>{const escape=str=>str.replace(/\\/i,"\\\\").replace(/"/g,'\\"');if(type===VALUE_TYPES.DATETIME){val=`"${val.toISOString()}"`}else if(type===VALUE_TYPES.STRING){val=`"${escape(val)}"`}else if(type===VALUE_TYPES.ARRAY){val=`[]`}else if(type===VALUE_TYPES.OBJECT){val=`{}`}else if(type===VALUE_TYPES.BINARY){val=`"${escape(ascii85.encode(val))}"`}else if(type===VALUE_TYPES.REFERENCE){val=`"${val.path}"`}return val};const queue=[];let outputCount=0;let objStart="",objEnd="";const buffer={output:"",enable:false,promise:null};return this.getNodeInfo(path).then(nodeInfo=>{if(!nodeInfo.exists){stream.write("null")}else if(nodeInfo.type===VALUE_TYPES.OBJECT){objStart="{";objEnd="}"}else if(nodeInfo.type===VALUE_TYPES.ARRAY){objStart="{";objEnd="}"}else{return this.getNodeValue(path).then(value=>{const val=stringifyValue(nodeInfo.type,value);return stream.write(val)})}let p=Promise.resolve();if(objStart){p=stream.write(objStart);if(!(p instanceof Promise)){p=Promise.resolve()}}return p.then(()=>{return this.getChildren(path).next(childInfo=>{if(childInfo.address){queue.push(childInfo)}else{const val=stringifyValue(childInfo.type,childInfo.value);const comma=outputCount>0?",":"";const key=typeof childInfo.index==="number"?`"${childInfo.index}"`:`"${childInfo.key}"`;const output=`${comma}${key}:${val}`;outputCount++;if(buffer.enable){buffer.output+=output}else{const flush=output=>{const p=stream.write(output);if(p instanceof Promise){buffer.enable=true;buffer.promise=p.then(()=>{const buffered=buffer.output;buffer.enable=false;buffer.output="";buffer.promise=null;if(buffered.length>0){return flush(buffered)}});return buffer.promise}};flush(output)}}})})}).then(()=>{return buffer.promise}).then(()=>{const next=()=>{if(queue.length===0){return}const childInfo=queue.shift();const comma=outputCount>0?",":"";const key=typeof childInfo.index==="number"?`"${childInfo.index}"`:`"${childInfo.key}"`;let p=stream.write(`${comma}${key}:`);outputCount++;if(!(p instanceof Promise)){p=Promise.resolve(p)}return p.then(()=>{return this.exportNode(childInfo.address.path,stream)}).then(()=>{return next()})};return next()}).then(()=>{if(objEnd){return stream.write(objEnd)}})}}module.exports={Storage:Storage,StorageSettings:StorageSettings,NodeNotFoundError:NodeNotFoundError,NodeRevisionError:NodeRevisionError}}).call(this,require("_process"))},{"./data-index":40,"./node-info":34,"./node-lock":35,"./node-value-types":36,"./promise-fs":40,_process:44,"acebase-core":11,colors:22,events:41}],40:[function(require,module,exports){},{}],41:[function(require,module,exports){var objectCreate=Object.create||objectCreatePolyfill;var objectKeys=Object.keys||objectKeysPolyfill;var bind=Function.prototype.bind||functionBindPolyfill;function EventEmitter(){if(!this._events||!Object.prototype.hasOwnProperty.call(this,"_events")){this._events=objectCreate(null);this._eventsCount=0}this._maxListeners=this._maxListeners||undefined}module.exports=EventEmitter;EventEmitter.EventEmitter=EventEmitter;EventEmitter.prototype._events=undefined;EventEmitter.prototype._maxListeners=undefined;var defaultMaxListeners=10;var hasDefineProperty;try{var o={};if(Object.defineProperty)Object.defineProperty(o,"x",{value:0});hasDefineProperty=o.x===0}catch(err){hasDefineProperty=false}if(hasDefineProperty){Object.defineProperty(EventEmitter,"defaultMaxListeners",{enumerable:true,get:function(){return defaultMaxListeners},set:function(arg){if(typeof arg!=="number"||arg<0||arg!==arg)throw new TypeError('"defaultMaxListeners" must be a positive number');defaultMaxListeners=arg}})}else{EventEmitter.defaultMaxListeners=defaultMaxListeners}EventEmitter.prototype.setMaxListeners=function setMaxListeners(n){if(typeof n!=="number"||n<0||isNaN(n))throw new TypeError('"n" argument must be a positive number');this._maxListeners=n;return this};function $getMaxListeners(that){if(that._maxListeners===undefined)return EventEmitter.defaultMaxListeners;return that._maxListeners}EventEmitter.prototype.getMaxListeners=function getMaxListeners(){return $getMaxListeners(this)};function emitNone(handler,isFn,self){if(isFn)handler.call(self);else{var len=handler.length;var listeners=arrayClone(handler,len);for(var i=0;i1)er=arguments[1];if(er instanceof Error){throw er}else{var err=new Error('Unhandled "error" event. ('+er+")");err.context=er;throw err}return false}handler=events[type];if(!handler)return false;var isFn=typeof handler==="function";len=arguments.length;switch(len){case 1:emitNone(handler,isFn,this);break;case 2:emitOne(handler,isFn,this,arguments[1]);break;case 3:emitTwo(handler,isFn,this,arguments[1],arguments[2]);break;case 4:emitThree(handler,isFn,this,arguments[1],arguments[2],arguments[3]);break;default:args=new Array(len-1);for(i=1;i0&&existing.length>m){existing.warned=true;var w=new Error("Possible EventEmitter memory leak detected. "+existing.length+' "'+String(type)+'" listeners '+"added. Use emitter.setMaxListeners() to "+"increase limit.");w.name="MaxListenersExceededWarning";w.emitter=target;w.type=type;w.count=existing.length;if(typeof console==="object"&&console.warn){console.warn("%s: %s",w.name,w.message)}}}}return target}EventEmitter.prototype.addListener=function addListener(type,listener){return _addListener(this,type,listener,false)};EventEmitter.prototype.on=EventEmitter.prototype.addListener;EventEmitter.prototype.prependListener=function prependListener(type,listener){return _addListener(this,type,listener,true)};function onceWrapper(){if(!this.fired){this.target.removeListener(this.type,this.wrapFn);this.fired=true;switch(arguments.length){case 0:return this.listener.call(this.target);case 1:return this.listener.call(this.target,arguments[0]);case 2:return this.listener.call(this.target,arguments[0],arguments[1]);case 3:return this.listener.call(this.target,arguments[0],arguments[1],arguments[2]);default:var args=new Array(arguments.length);for(var i=0;i=0;i--){if(list[i]===listener||list[i].listener===listener){originalListener=list[i].listener;position=i;break}}if(position<0)return this;if(position===0)list.shift();else spliceOne(list,position);if(list.length===1)events[type]=list[0];if(events.removeListener)this.emit("removeListener",type,originalListener||listener)}return this};EventEmitter.prototype.removeAllListeners=function removeAllListeners(type){var listeners,events,i;events=this._events;if(!events)return this;if(!events.removeListener){if(arguments.length===0){this._events=objectCreate(null);this._eventsCount=0}else if(events[type]){if(--this._eventsCount===0)this._events=objectCreate(null);else delete events[type]}return this}if(arguments.length===0){var keys=objectKeys(events);var key;for(i=0;i=0;i--){this.removeListener(type,listeners[i])}}return this};function _listeners(target,type,unwrap){var events=target._events;if(!events)return[];var evlistener=events[type];if(!evlistener)return[];if(typeof evlistener==="function")return unwrap?[evlistener.listener||evlistener]:[evlistener];return unwrap?unwrapListeners(evlistener):arrayClone(evlistener,evlistener.length)}EventEmitter.prototype.listeners=function listeners(type){return _listeners(this,type,true)};EventEmitter.prototype.rawListeners=function rawListeners(type){return _listeners(this,type,false)};EventEmitter.listenerCount=function(emitter,type){if(typeof emitter.listenerCount==="function"){return emitter.listenerCount(type)}else{return listenerCount.call(emitter,type)}};EventEmitter.prototype.listenerCount=listenerCount;function listenerCount(type){var events=this._events;if(events){var evlistener=events[type];if(typeof evlistener==="function"){return 1}else if(evlistener){return evlistener.length}}return 0}EventEmitter.prototype.eventNames=function eventNames(){return this._eventsCount>0?Reflect.ownKeys(this._events):[]};function spliceOne(list,index){for(var i=index,k=i+1,n=list.length;k1){for(var i=1;i=len)return x;switch(x){case"%s":return String(args[i++]);case"%d":return Number(args[i++]);case"%j":try{return JSON.stringify(args[i++])}catch(_){return"[Circular]"}default:return x}}));for(var x=args[i];i=3)ctx.depth=arguments[2];if(arguments.length>=4)ctx.colors=arguments[3];if(isBoolean(opts)){ctx.showHidden=opts}else if(opts){exports._extend(ctx,opts)}if(isUndefined(ctx.showHidden))ctx.showHidden=false;if(isUndefined(ctx.depth))ctx.depth=2;if(isUndefined(ctx.colors))ctx.colors=false;if(isUndefined(ctx.customInspect))ctx.customInspect=true;if(ctx.colors)ctx.stylize=stylizeWithColor;return formatValue(ctx,obj,ctx.depth)}exports.inspect=inspect;inspect.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]};inspect.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"};function stylizeWithColor(str,styleType){var style=inspect.styles[styleType];if(style){return"["+inspect.colors[style][0]+"m"+str+"["+inspect.colors[style][1]+"m"}else{return str}}function stylizeNoColor(str,styleType){return str}function arrayToHash(array){var hash={};array.forEach((function(val,idx){hash[val]=true}));return hash}function formatValue(ctx,value,recurseTimes){if(ctx.customInspect&&value&&isFunction(value.inspect)&&value.inspect!==exports.inspect&&!(value.constructor&&value.constructor.prototype===value)){var ret=value.inspect(recurseTimes,ctx);if(!isString(ret)){ret=formatValue(ctx,ret,recurseTimes)}return ret}var primitive=formatPrimitive(ctx,value);if(primitive){return primitive}var keys=Object.keys(value);var visibleKeys=arrayToHash(keys);if(ctx.showHidden){keys=Object.getOwnPropertyNames(value)}if(isError(value)&&(keys.indexOf("message")>=0||keys.indexOf("description")>=0)){return formatError(value)}if(keys.length===0){if(isFunction(value)){var name=value.name?": "+value.name:"";return ctx.stylize("[Function"+name+"]","special")}if(isRegExp(value)){return ctx.stylize(RegExp.prototype.toString.call(value),"regexp")}if(isDate(value)){return ctx.stylize(Date.prototype.toString.call(value),"date")}if(isError(value)){return formatError(value)}}var base="",array=false,braces=["{","}"];if(isArray(value)){array=true;braces=["[","]"]}if(isFunction(value)){var n=value.name?": "+value.name:"";base=" [Function"+n+"]"}if(isRegExp(value)){base=" "+RegExp.prototype.toString.call(value)}if(isDate(value)){base=" "+Date.prototype.toUTCString.call(value)}if(isError(value)){base=" "+formatError(value)}if(keys.length===0&&(!array||value.length==0)){return braces[0]+base+braces[1]}if(recurseTimes<0){if(isRegExp(value)){return ctx.stylize(RegExp.prototype.toString.call(value),"regexp")}else{return ctx.stylize("[Object]","special")}}ctx.seen.push(value);var output;if(array){output=formatArray(ctx,value,recurseTimes,visibleKeys,keys)}else{output=keys.map((function(key){return formatProperty(ctx,value,recurseTimes,visibleKeys,key,array)}))}ctx.seen.pop();return reduceToSingleString(output,base,braces)}function formatPrimitive(ctx,value){if(isUndefined(value))return ctx.stylize("undefined","undefined");if(isString(value)){var simple="'"+JSON.stringify(value).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return ctx.stylize(simple,"string")}if(isNumber(value))return ctx.stylize(""+value,"number");if(isBoolean(value))return ctx.stylize(""+value,"boolean");if(isNull(value))return ctx.stylize("null","null")}function formatError(value){return"["+Error.prototype.toString.call(value)+"]"}function formatArray(ctx,value,recurseTimes,visibleKeys,keys){var output=[];for(var i=0,l=value.length;i-1){if(array){str=str.split("\n").map((function(line){return" "+line})).join("\n").substr(2)}else{str="\n"+str.split("\n").map((function(line){return" "+line})).join("\n")}}}else{str=ctx.stylize("[Circular]","special")}}if(isUndefined(name)){if(array&&key.match(/^\d+$/)){return str}name=JSON.stringify(""+key);if(name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)){name=name.substr(1,name.length-2);name=ctx.stylize(name,"name")}else{name=name.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'");name=ctx.stylize(name,"string")}}return name+": "+str}function reduceToSingleString(output,base,braces){var numLinesEst=0;var length=output.reduce((function(prev,cur){numLinesEst++;if(cur.indexOf("\n")>=0)numLinesEst++;return prev+cur.replace(/\u001b\[\d\d?m/g,"").length+1}),0);if(length>60){return braces[0]+(base===""?"":base+"\n ")+" "+output.join(",\n ")+" "+braces[1]}return braces[0]+base+" "+output.join(", ")+" "+braces[1]}function isArray(ar){return Array.isArray(ar)}exports.isArray=isArray;function isBoolean(arg){return typeof arg==="boolean"}exports.isBoolean=isBoolean;function isNull(arg){return arg===null}exports.isNull=isNull;function isNullOrUndefined(arg){return arg==null}exports.isNullOrUndefined=isNullOrUndefined;function isNumber(arg){return typeof arg==="number"}exports.isNumber=isNumber;function isString(arg){return typeof arg==="string"}exports.isString=isString;function isSymbol(arg){return typeof arg==="symbol"}exports.isSymbol=isSymbol;function isUndefined(arg){return arg===void 0}exports.isUndefined=isUndefined;function isRegExp(re){return isObject(re)&&objectToString(re)==="[object RegExp]"}exports.isRegExp=isRegExp;function isObject(arg){return typeof arg==="object"&&arg!==null}exports.isObject=isObject;function isDate(d){return isObject(d)&&objectToString(d)==="[object Date]"}exports.isDate=isDate;function isError(e){return isObject(e)&&(objectToString(e)==="[object Error]"||e instanceof Error)}exports.isError=isError;function isFunction(arg){return typeof arg==="function"}exports.isFunction=isFunction;function isPrimitive(arg){return arg===null||typeof arg==="boolean"||typeof arg==="number"||typeof arg==="string"||typeof arg==="symbol"||typeof arg==="undefined"}exports.isPrimitive=isPrimitive;exports.isBuffer=require("./support/isBuffer");function objectToString(o){return Object.prototype.toString.call(o)}function pad(n){return n<10?"0"+n.toString(10):n.toString(10)}var months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function timestamp(){var d=new Date;var time=[pad(d.getHours()),pad(d.getMinutes()),pad(d.getSeconds())].join(":");return[d.getDate(),months[d.getMonth()],time].join(" ")}exports.log=function(){console.log("%s - %s",timestamp(),exports.format.apply(exports,arguments))};exports.inherits=require("inherits");exports._extend=function(origin,add){if(!add||!isObject(add))return origin;var keys=Object.keys(add);var i=keys.length;while(i--){origin[keys[i]]=add[keys[i]]}return origin};function hasOwnProperty(obj,prop){return Object.prototype.hasOwnProperty.call(obj,prop)}}).call(this,require("_process"),typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./support/isBuffer":45,_process:44,inherits:42}]},{},[33])(33)})); \ No newline at end of file +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.acebase=f()}})((function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,(function(r){var n=e[i][1][r];return o(n||r)}),p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i=7&&stringLength<=10)return true;return false};cuid.fingerprint=fingerprint;module.exports=cuid},{"./lib/fingerprint.js":2,"./lib/pad.js":3}],2:[function(require,module,exports){var pad=require("./pad.js");var env=typeof window==="object"?window:self;var globalCount=Object.keys(env).length;var mimeTypesLength=navigator.mimeTypes?navigator.mimeTypes.length:0;var clientId=pad((mimeTypesLength+navigator.userAgent.length).toString(36)+globalCount.toString(36),4);module.exports=function fingerprint(){return clientId}},{"./pad.js":3}],3:[function(require,module,exports){module.exports=function pad(num,size){var s="000000000"+num;return s.substr(s.length-size)}},{}],4:[function(require,module,exports){const{EventEmitter:EventEmitter}=require("events");const{DataReference:DataReference,DataReferenceQuery:DataReferenceQuery}=require("./data-reference");const{TypeMappings:TypeMappings}=require("./type-mappings");class AceBaseSettings{constructor(options){this.logLevel=options.logLevel||"log"}}class AceBaseBase extends EventEmitter{constructor(dbname,options){super();if(!options){options={}}this.once("ready",()=>{this._ready=true});this.types=new TypeMappings(this)}ready(callback=undefined){if(this._ready===true){callback&&callback();return Promise.resolve()}else{let resolve;const promise=new Promise(res=>resolve=res);this.on("ready",()=>{resolve();callback&&callback()});return promise}}get isReady(){return this._ready===true}ref(path){return new DataReference(this,path)}get root(){return this.ref("")}query(path){const ref=new DataReference(this,path);return new DataReferenceQuery(ref)}get indexes(){return{get:()=>{return this.api.getIndexes()},create:(path,key,options)=>{return this.api.createIndex(path,key,options)}}}}module.exports={AceBaseBase:AceBaseBase,AceBaseSettings:AceBaseSettings}},{"./data-reference":7,"./type-mappings":16,events:41}],5:[function(require,module,exports){class Api{stats(options=undefined){}subscribe(path,event,callback){}unsubscribe(path,event,callback){}update(path,updates){}set(path,value){}get(path,options){}exists(path){}query(path,query,options){}createIndex(path,key){}getIndexes(){}}module.exports={Api:Api}},{}],6:[function(require,module,exports){const c=function(input,length,result){var i,j,n,b=[0,0,0,0,0];for(i=0;i";return ret},decode:function(input){if(!input.startsWith("<~")||!input.endsWith("~>")){throw new Error("Invalid input string")}input=input.substr(2,input.length-4);var n=input.length,r=[],b=[0,0,0,0,0],i,j,t,x,y,d;for(i=0;i>>=8;y=t&255;t>>>=8;r.push(t>>>8,t&255,y,x);for(j=d;j<5;++j,r.pop());i+=4}const data=new Uint8Array(r);return data.buffer.slice(data.byteOffset,data.byteOffset+data.byteLength)}};module.exports=ascii85},{}],7:[function(require,module,exports){const{DataSnapshot:DataSnapshot}=require("./data-snapshot");const{EventStream:EventStream,EventPublisher:EventPublisher}=require("./subscription");const{ID:ID}=require("./id");const debug=require("./debug");const{PathInfo:PathInfo}=require("./path-info");class DataRetrievalOptions{constructor(options){if(!options){options={}}if(typeof options.include!=="undefined"&&!(options.include instanceof Array)){throw new TypeError(`options.include must be an array`)}if(typeof options.exclude!=="undefined"&&!(options.exclude instanceof Array)){throw new TypeError(`options.exclude must be an array`)}if(typeof options.child_objects!=="undefined"&&typeof options.child_objects!=="boolean"){throw new TypeError(`options.child_objects must be a boolean`)}if(typeof options.allow_cache!=="undefined"&&typeof options.allow_cache!=="boolean"){throw new TypeError(`options.allow_cache must be a boolean`)}this.include=options.include||undefined;this.exclude=options.exclude||undefined;this.child_objects=typeof options.child_objects==="boolean"?options.child_objects:undefined;this.allow_cache=typeof options.allow_cache==="boolean"?options.allow_cache:undefined}}class QueryDataRetrievalOptions extends DataRetrievalOptions{constructor(options){super(options);if(typeof options.snapshots!=="undefined"&&typeof options.snapshots!=="boolean"){throw new TypeError(`options.snapshots must be an array`)}this.snapshots=typeof options.snapshots==="boolean"?options.snapshots:undefined}}const _private=Symbol("private");class DataReference{constructor(db,path,vars){if(!path){path=""}path=path.replace(/^\/|\/$/g,"");const pathInfo=PathInfo.get(path);const key=pathInfo.key;const callbacks=[];this[_private]={get path(){return path},get key(){return key},get callbacks(){return callbacks},vars:vars||{}};this.db=db}get path(){return this[_private].path}get key(){return this[_private].key}get parent(){let currentPath=PathInfo.fillVariables2(this.path,this.vars);const info=PathInfo.get(currentPath);if(info.parentPath===null){return null}return new DataReference(this.db,info.parentPath)}get vars(){return this[_private].vars}child(childPath){childPath=typeof childPath==="number"?childPath:childPath.replace(/^\/|\/$/g,"");const currentPath=PathInfo.fillVariables2(this.path,this.vars);const targetPath=PathInfo.getChildPath(currentPath,childPath);return new DataReference(this.db,targetPath)}set(value,onComplete=undefined){if(this.isWildcardPath){throw new Error(`Cannot set the value of a path with wildcards and/or variables`)}if(this.parent===null){throw new Error(`Cannot set the root object. Use update, or set individual child properties`)}if(typeof value==="undefined"){throw new TypeError(`Cannot store value undefined`)}value=this.db.types.serialize(this.path,value);return this.db.api.set(this.path,value).then(res=>{if(typeof onComplete==="function"){try{onComplete(null,this)}catch(err){console.error(`Error in onComplete callback:`,err)}}}).catch(err=>{if(typeof onComplete==="function"){try{onComplete(err)}catch(err){console.error(`Error in onComplete callback:`,err)}}else{throw err}}).then(()=>{return this})}update(updates,onComplete=undefined){if(this.isWildcardPath){throw new Error(`Cannot update the value of a path with wildcards and/or variables`)}let promise;if(typeof updates!=="object"||updates instanceof Array||updates instanceof ArrayBuffer||updates instanceof Date){promise=this.set(updates)}else if(Object.keys(updates).length===0){console.warn(`update called on path "/${this.path}", but there is nothing to update`);return Promise.resolve()}else{updates=this.db.types.serialize(this.path,updates);promise=this.db.api.update(this.path,updates)}return promise.then(()=>{if(typeof onComplete==="function"){try{onComplete(null,this)}catch(err){console.error(`Error in onComplete callback:`,err)}}}).catch(err=>{if(typeof onComplete==="function"){try{onComplete(err)}catch(err){console.error(`Error in onComplete callback:`,err)}}else{throw err}}).then(()=>{return this})}transaction(callback){if(this.isWildcardPath){throw new Error(`Cannot start a transaction on a path with wildcards and/or variables`)}let throwError;let cb=currentValue=>{currentValue=this.db.types.deserialize(this.path,currentValue);const snap=new DataSnapshot(this,currentValue);let newValue;try{newValue=callback(snap)}catch(err){throwError=err;return}if(newValue instanceof Promise){return newValue.then(val=>{return this.db.types.serialize(this.path,val)}).catch(err=>{throwError=err;return})}else{return this.db.types.serialize(this.path,newValue)}};return this.db.api.transaction(this.path,cb).then(result=>{if(throwError){throw throwError}return this})}on(event,callback,cancelCallbackOrContext,context){if(this.path===""&&["value","notify_value","child_changed","notify_child_changed"].includes(event)){console.warn(`WARNING: Listening for value and child_changed events on the root node is a bad practice`)}const cancelCallback=typeof cancelCallbackOrContext==="function"&&cancelCallbackOrContext;context=typeof cancelCallbackOrContext==="object"?cancelCallbackOrContext:context;const useCallback=typeof callback==="function";let eventPublisher=null;const eventStream=new EventStream(publisher=>{eventPublisher=publisher});let cb={subscr:eventStream,original:callback,ours:(err,path,newValue,oldValue)=>{if(err){debug.error(`Error getting data for event ${event} on path "${path}"`,err);return}let ref=this.db.ref(path);ref[_private].vars=PathInfo.extractVariables(this.path,path);let callbackObject;if(event.startsWith("notify_")){callbackObject=ref}else{const isRemoved=event==="child_removed";const val=this.db.types.deserialize(path,isRemoved?oldValue:newValue);const snap=new DataSnapshot(ref,val,isRemoved);callbackObject=snap}try{useCallback&&callback.call(context||null,callbackObject)}catch(err){console.error(`ERROR firing "${event}" callback for path "${path}":`,err)}let keep=eventPublisher.publish(callbackObject);if(!keep&&!useCallback){let callbacks=this[_private].callbacks;callbacks.splice(callbacks.indexOf(cb),1);this.db.api.unsubscribe(this.path,event,cb.ours)}}};this[_private].callbacks.push(cb);let authorized=this.db.api.subscribe(this.path,event,cb.ours);const allSubscriptionsStoppedCallback=()=>{let callbacks=this[_private].callbacks;callbacks.splice(callbacks.indexOf(cb),1);this.db.api.unsubscribe(this.path,event,cb.ours)};if(authorized instanceof Promise){authorized.then(()=>{eventPublisher.start(allSubscriptionsStoppedCallback)}).catch(err=>{let callbacks=this[_private].callbacks;callbacks.splice(callbacks.indexOf(cb),1);this.db.api.unsubscribe(this.path,event,cb.ours);eventPublisher.cancel(err.message);cancelCallback&&cancelCallback(err.message)})}else{eventPublisher.start(allSubscriptionsStoppedCallback)}if(callback&&!this.isWildcardPath){if(event==="value"){this.get(snap=>{eventPublisher.publish(snap);useCallback&&callback(snap)})}else if(event==="child_added"){this.get(snap=>{const val=snap.val();if(val===null||typeof val!=="object"){return}Object.keys(val).forEach(key=>{let childSnap=new DataSnapshot(this.child(key),val[key]);eventPublisher.publish(childSnap);useCallback&&callback(childSnap)})})}else if(event==="notify_child_added"){const step=100;let limit=step,skip=0;const more=()=>{this.db.api.reflect(this.path,"children",{limit:limit,skip:skip}).then(children=>{children.list.forEach(child=>{const childRef=this.child(child.key);eventPublisher.publish(childRef);useCallback&&callback(childRef)});if(children.more){skip+=step;more()}})};more()}}return eventStream}off(event=undefined,callback=undefined){const callbacks=this[_private].callbacks;if(callback){const cb=callbacks.find(cb=>cb.original===callback);if(!cb){debug.error(`Can't find specified callback to unsubscribe from (path: "${this.path}", event: ${event}, callback: ${callback})`);return}callbacks.splice(callbacks.indexOf(cb),1);callback=cb.ours;cb.subscr.unsubscribe(callback)}else{callbacks.splice(0,callbacks.length).forEach(cb=>{cb.subscr.unsubscribe()})}this.db.api.unsubscribe(this.path,event,callback);return this}get(optionsOrCallback=undefined,callback=undefined){if(this.isWildcardPath){throw new Error(`Cannot get the value of a path with wildcards and/or variables. Use .query() instead`)}callback=typeof optionsOrCallback==="function"?optionsOrCallback:typeof callback==="function"?callback:undefined;const options=typeof optionsOrCallback==="object"?optionsOrCallback:new DataRetrievalOptions({allow_cache:true});if(typeof options.allow_cache==="undefined"){options.allow_cache=true}const promise=this.db.api.get(this.path,options).then(value=>{value=this.db.types.deserialize(this.path,value);const snapshot=new DataSnapshot(this,value);return snapshot});if(callback){promise.then(callback);return}else{return promise}}once(event,options){if(event==="value"&&!this.isWildcardPath){return this.get(options)}return new Promise((resolve,reject)=>{const callback=snap=>{this.off(event,snap);resolve(snap)};this.on(event,callback)})}push(value=undefined,onComplete=undefined){if(this.isWildcardPath){throw new Error(`Cannot push to a path with wildcards and/or variables`)}const id=ID.generate();const ref=this.child(id);ref.__pushed=true;if(typeof value!=="undefined"){return ref.set(value,onComplete).then(res=>ref)}else{return ref}}remove(){if(this.isWildcardPath){throw new Error(`Cannot remove a path with wildcards and/or variables. Use query().remove instead`)}if(this.parent===null){throw new Error(`Cannot remove the top node`)}return this.set(null)}exists(){if(this.isWildcardPath){throw new Error(`Cannot push to a path with wildcards and/or variables`)}return this.db.api.exists(this.path)}get isWildcardPath(){return this.path.indexOf("*")>=0||this.path.indexOf("$")>=0}query(){return new DataReferenceQuery(this)}reflect(type,args){if(this.pathHasVariables){throw new Error(`Cannot reflect on a path with wildcards and/or variables`)}return this.db.api.reflect(this.path,type,args)}export(stream,options={format:"json"}){return this.db.api.export(this.path,stream,options)}}class DataReferenceQuery{constructor(ref){this.ref=ref;this[_private]={filters:[],skip:0,take:0,order:[]}}filter(key,op,compare){if((op==="in"||op==="!in")&&(!(compare instanceof Array)||compare.length===0)){throw new Error(`${op} filter for ${key} must supply an Array compare argument containing at least 1 value`)}if((op==="between"||op==="!between")&&(!(compare instanceof Array)||compare.length!==2)){throw new Error(`${op} filter for ${key} must supply an Array compare argument containing 2 values`)}if((op==="matches"||op==="!matches")&&!(compare instanceof RegExp)){throw new Error(`${op} filter for ${key} must supply a RegExp compare argument`)}if((op==="contains"||op==="!contains")&&(typeof compare==="object"&&!(compare instanceof Array)&&!(compare instanceof Date)||compare instanceof Array&&compare.length===0)){throw new Error(`${op} filter for ${key} must supply a simple value or (non-zero length) array compare argument`)}this[_private].filters.push({key:key,op:op,compare:compare});return this}where(key,op,compare){return this.filter(key,op,compare)}take(n){this[_private].take=n;return this}skip(n){this[_private].skip=n;return this}sort(key,ascending=true){if(typeof key!=="string"){throw`key must be a string`}this[_private].order.push({key:key,ascending:ascending});return this}order(key,ascending=true){return this.sort(key,ascending)}get(optionsOrCallback=undefined,callback=undefined){callback=typeof optionsOrCallback==="function"?optionsOrCallback:typeof callback==="function"?callback:undefined;const options=typeof optionsOrCallback==="object"?optionsOrCallback:new QueryDataRetrievalOptions({snapshots:true,allow_cache:true});if(typeof options.snapshots==="undefined"){options.snapshots=true}if(typeof options.allow_cache==="undefined"){options.allow_cache=true}options.eventHandler=ev=>{if(!this._events||!this._events[ev.name]){return false}const listeners=this._events[ev.name];if(typeof listeners!=="object"||listeners.length===0){return false}if(["add","change","remove"].includes(ev.name)){const ref=new DataReference(this.ref.db,ev.path);const eventData={name:ev.name};if(options.snapshots&&ev.name!=="remove"){const val=db.types.deserialize(ev.path,ev.value);eventData.snapshot=new DataSnapshot(ref,val,false)}else{eventData.ref=ref}ev=eventData}listeners.forEach(callback=>{try{callback(ev)}catch(e){}})};options.monitor={add:false,change:false,remove:false};if(this._events){if(this._events["add"]&&this._events["add"].length>0){options.monitor.add=true}if(this._events["change"]&&this._events["change"].length>0){options.monitor.change=true}if(this._events["remove"]&&this._events["remove"].length>0){options.monitor.remove=true}}const db=this.ref.db;return db.api.query(this.ref.path,this[_private],options).catch(err=>{throw new Error(err)}).then(results=>{results.forEach((result,index)=>{if(options.snapshots){const val=db.types.deserialize(result.path,result.val);results[index]=new DataSnapshot(db.ref(result.path),val)}else{results[index]=db.ref(result)}});if(options.snapshots){return DataSnapshotsArray.from(results)}else{return DataReferencesArray.from(results)}}).then(results=>{callback&&callback(results);return results})}getRefs(callback=undefined){return this.get({snapshots:false},callback)}remove(callback){return this.get({snapshots:false}).then(refs=>{const promises=[];return Promise.all(refs.map(ref=>ref.remove())).then(()=>{callback&&callback()})})}on(event,callback){if(!this._events){this._events={}}if(!this._events[event]){this._events[event]=[]}this._events[event].push(callback);return this}off(event,callback){if(!this._events){return this}if(typeof event==="undefined"){this._events={};return this}if(!this._events[event]){return this}if(typeof callback==="undefined"){delete this._events[event];return this}const index=!this._events[event].indexOf(callback);if(!~index){return this}this._events[event].splice(index,1);return this}}class DataSnapshotsArray extends Array{static from(snaps){const arr=new DataSnapshotsArray(snaps.length);snaps.forEach((snap,i)=>arr[i]=snap);return arr}getValues(){return this.map(snap=>snap.val())}}class DataReferencesArray extends Array{static from(refs){const arr=new DataReferencesArray(refs.length);refs.forEach((ref,i)=>arr[i]=ref);return arr}getPaths(){return this.map(ref=>ref.path)}}module.exports={DataReference:DataReference,DataReferenceQuery:DataReferenceQuery,DataRetrievalOptions:DataRetrievalOptions,QueryDataRetrievalOptions:QueryDataRetrievalOptions}},{"./data-snapshot":8,"./debug":9,"./id":10,"./path-info":12,"./subscription":14}],8:[function(require,module,exports){const{DataReference:DataReference}=require("./data-reference");const{getPathKeys:getPathKeys}=require("./path-info");const getChild=(snapshot,path)=>{if(!snapshot.exists()){return null}let child=snapshot.val();getPathKeys(path).every(key=>{child=child[key];return typeof child!=="undefined"});return child||null};const getChildren=snapshot=>{if(!snapshot.exists()){return[]}let value=snapshot.val();if(value instanceof Array){return new Array(value.length).map((v,i)=>i)}if(typeof value==="object"){return Object.keys(value)}return[]};class DataSnapshot{constructor(ref,value,isRemoved=false){this.ref=ref;this.val=()=>{return value};this.exists=()=>{if(isRemoved){return false}return value!==null&&typeof value!=="undefined"}}child(path){let child=getChild(this,path);return new DataSnapshot(this.ref.child(path),child)}hasChild(path){return getChild(this,path)!==null}hasChildren(){return getChildren(this).length>0}numChildren(){return getChildren(this).length}forEach(callback){const value=this.val();return getChildren(this).every((key,i)=>{const snap=new DataSnapshot(this.ref.child(key),value[key]);return callback(snap)})}get key(){return this.ref.key}}module.exports={DataSnapshot:DataSnapshot}},{"./data-reference":7,"./path-info":12}],9:[function(require,module,exports){class DebugLogger{constructor(level="log",prefix=""){this.prefix=prefix;this.setLevel(level)}setLevel(level){const prefix=this.prefix?this.prefix:"";this.level=level;this.verbose=["verbose"].includes(level)?console.log.bind(console,prefix):()=>{};this.log=["verbose","log"].includes(level)?console.log.bind(console,prefix):()=>{};this.warn=["verbose","log","warn"].includes(level)?console.warn.bind(console,prefix):()=>{};this.error=["verbose","log","warn","error"].includes(level)?console.error.bind(console,prefix):()=>{};this.write=console.log.bind(console)}}module.exports=DebugLogger},{}],10:[function(require,module,exports){const cuid=require("cuid");class ID{static generate(){return cuid().slice(1)}}module.exports={ID:ID}},{cuid:1}],11:[function(require,module,exports){const{AceBaseBase:AceBaseBase,AceBaseSettings:AceBaseSettings}=require("./acebase-base");const{Api:Api}=require("./api");const{DataReference:DataReference,DataReferenceQuery:DataReferenceQuery,DataRetrievalOptions:DataRetrievalOptions,QueryDataRetrievalOptions:QueryDataRetrievalOptions}=require("./data-reference");const{DataSnapshot:DataSnapshot}=require("./data-snapshot");const DebugLogger=require("./debug");const{ID:ID}=require("./id");const{PathReference:PathReference}=require("./path-reference");const{EventStream:EventStream,EventPublisher:EventPublisher,EventSubscription:EventSubscription}=require("./subscription");const Transport=require("./transport");const{TypeMappings:TypeMappings,TypeMappingOptions:TypeMappingOptions}=require("./type-mappings");const Utils=require("./utils");const{PathInfo:PathInfo}=require("./path-info");const ascii85=require("./ascii85");module.exports={AceBaseBase:AceBaseBase,AceBaseSettings:AceBaseSettings,Api:Api,DataReference:DataReference,DataReferenceQuery:DataReferenceQuery,DataRetrievalOptions:DataRetrievalOptions,QueryDataRetrievalOptions:QueryDataRetrievalOptions,DataSnapshot:DataSnapshot,DebugLogger:DebugLogger,ID:ID,PathReference:PathReference,EventStream:EventStream,EventPublisher:EventPublisher,EventSubscription:EventSubscription,Transport:Transport,TypeMappings:TypeMappings,TypeMappingOptions:TypeMappingOptions,Utils:Utils,PathInfo:PathInfo,ascii85:ascii85}},{"./acebase-base":4,"./api":5,"./ascii85":6,"./data-reference":7,"./data-snapshot":8,"./debug":9,"./id":10,"./path-info":12,"./path-reference":13,"./subscription":14,"./transport":15,"./type-mappings":16,"./utils":17}],12:[function(require,module,exports){function getPathKeys(path){if(path.length===0){return[]}let keys=path.replace(/\[/g,"/[").split("/");keys.forEach((key,index)=>{if(key.startsWith("[")){keys[index]=parseInt(key.substr(1,key.length-2))}});return keys}function getPathInfo(path){if(path.length===0){return{parent:null,key:""}}const i=Math.max(path.lastIndexOf("/"),path.lastIndexOf("["));const parentPath=i<0?"":path.substr(0,i);let key=i<0?path:path.substr(i);if(key.startsWith("[")){key=parseInt(key.substr(1,key.length-2))}else if(key.startsWith("/")){key=key.substr(1)}if(parentPath===path){parentPath=null}return{parent:parentPath,key:key}}function getChildPath(path,key){if(path.length===0){if(typeof key==="number"){throw new TypeError("Cannot add array index to root path!")}return key}if(typeof key==="number"){return`${path}[${key}]`}return`${path}/${key}`}class PathInfo{static get(path){return new PathInfo(path)}static getChildPath(path,childKey){return getChildPath(path,childKey)}static getPathKeys(path){return getPathKeys(path)}constructor(path){this.path=path}get key(){return getPathInfo(this.path).key}get parentPath(){return getPathInfo(this.path).parent}childPath(childKey){return getChildPath(`${this.path}`,childKey)}get pathKeys(){return getPathKeys(this.path)}static extractVariables(varPath,fullPath){if(!varPath.includes("*")&&!varPath.includes("$")){return[]}const keys=getPathKeys(varPath);const pathKeys=getPathKeys(fullPath);let count=0;const variables={get length(){return count}};keys.forEach((key,index)=>{const pathKey=pathKeys[index];if(key==="*"){variables[count++]=pathKey}else if(typeof key==="string"&&key[0]==="$"){variables[count++]=pathKey;variables[key]=pathKey;const varName=key.slice(1);if(typeof variables[varName]==="undefined"){variables[varName]=pathKey}}});return variables}static fillVariables(varPath,fullPath){if(varPath.indexOf("*")<0&&varPath.indexOf("$")<0){return varPath}const keys=getPathKeys(varPath);const pathKeys=getPathKeys(fullPath);let merged=keys.map((key,index)=>{if(key===pathKeys[index]||index>=pathKeys.length){return key}else if(typeof key==="string"&&(key==="*"||key[0]==="$")){return pathKeys[index]}else{throw new Error(`Path "${fullPath}" cannot be used to fill variables of path "${this.path}" because they do not match`)}});let mergedPath="";merged.forEach(key=>{if(typeof key==="number"){mergedPath+=`[${key}]`}else{if(mergedPath.length>0){mergedPath+="/"}mergedPath+=key}});return mergedPath}static fillVariables2(varPath,vars){if(typeof vars!=="object"||Object.keys(vars).length===0){return varPath}let pathKeys=getPathKeys(varPath);let n=0;const targetPath=pathKeys.reduce((path,key)=>{if(key==="*"||key.startsWith("$")){key=vars[n++]}if(typeof key==="number"){return`${path}[${key}]`}else{return`${path}/${key}`}},"");return targetPath}equals(otherPath){if(this.path===otherPath){return true}const keys=getPathKeys(this.path);const otherKeys=getPathKeys(otherPath);if(keys.length!==otherKeys.length){return false}return keys.every((key,index)=>{const otherKey=otherKeys[index];return otherKey===key||typeof otherKey==="string"&&(otherKey==="*"||otherKey[0]==="$")||typeof key==="string"&&(key==="*"||key[0]==="$")})}isAncestorOf(descendantPath){if(descendantPath===""||this.path===descendantPath){return false}if(this.path===""){return true}const ancestorKeys=getPathKeys(this.path);const descendantKeys=getPathKeys(descendantPath);if(ancestorKeys.length>=descendantKeys.length){return false}return ancestorKeys.every((key,index)=>{const otherKey=descendantKeys[index];return otherKey===key||typeof otherKey==="string"&&(otherKey==="*"||otherKey[0]==="$")||typeof key==="string"&&(key==="*"||key[0]==="$")})}isDescendantOf(ancestorPath){if(this.path===""||this.path===ancestorPath){return false}if(ancestorPath===""){return true}const ancestorKeys=getPathKeys(ancestorPath);const descendantKeys=getPathKeys(this.path);if(ancestorKeys.length>=descendantKeys.length){return false}return ancestorKeys.every((key,index)=>{const otherKey=descendantKeys[index];return otherKey===key||typeof otherKey==="string"&&(otherKey==="*"||otherKey[0]==="$")||typeof key==="string"&&(key==="*"||key[0]==="$")})}isChildOf(otherPath){if(this.path===""){return false}const parentInfo=PathInfo.get(this.parentPath);return parentInfo.equals(otherPath)}isParentOf(otherPath){if(otherPath===""){return false}const parentInfo=PathInfo.get(PathInfo.get(otherPath).parentPath);return parentInfo.equals(this.path)}}module.exports={getPathInfo:getPathInfo,getChildPath:getChildPath,getPathKeys:getPathKeys,PathInfo:PathInfo}},{}],13:[function(require,module,exports){class PathReference{constructor(path){this.path=path}}module.exports={PathReference:PathReference}},{}],14:[function(require,module,exports){class EventSubscription{constructor(stop){this.stop=stop;this._internal={state:"init",cancelReason:undefined,activatePromises:[]}}activated(callback=undefined){if(callback){this._internal.activatePromises.push({callback:callback});if(this._internal.state==="active"){callback(true)}else if(this._internal.state==="canceled"){callback(false,this._internal.cancelReason)}}return new Promise((resolve,reject)=>{if(this._internal.state==="active"){return resolve()}else if(this._internal.state==="canceled"&&!callback){return reject(new Error(this._internal.cancelReason))}this._internal.activatePromises.push({resolve:resolve,reject:callback?()=>{}:reject})})}_setActivationState(activated,cancelReason){this._internal.cancelReason=cancelReason;this._internal.state=activated?"active":"canceled";while(this._internal.activatePromises.length>0){const p=this._internal.activatePromises.shift();if(activated){p.callback&&p.callback(true);p.resolve&&p.resolve()}else{p.callback&&p.callback(false,cancelReason);p.reject&&p.reject(cancelReason)}}}}class EventPublisher{constructor(publish,start,cancel){this.publish=publish;this.start=start;this.cancel=cancel}}class EventStream{constructor(eventPublisherCallback){const subscribers=[];let noMoreSubscribersCallback;let activationState;const _stoppedState="stopped (no more subscribers)";this.subscribe=(callback,activationCallback)=>{if(typeof callback!=="function"){throw new TypeError("callback must be a function")}else if(activationState===_stoppedState){throw new Error("stream can't be used anymore because all subscribers were stopped")}const sub={callback:callback,activationCallback:function(activated,cancelReason){activationCallback&&activationCallback(activated,cancelReason);this.subscription._setActivationState(activated,cancelReason)},subscription:new EventSubscription((function stop(){subscribers.splice(subscribers.indexOf(this),1);checkActiveSubscribers()}))};subscribers.push(sub);if(typeof activationState!=="undefined"){if(activationState===true){activationCallback&&activationCallback(true);sub.subscription._setActivationState(true)}else if(typeof activationState==="string"){activationCallback&&activationCallback(false,activationState);sub.subscription._setActivationState(false,activationState)}}return sub.subscription};const checkActiveSubscribers=()=>{if(subscribers.length===0){noMoreSubscribersCallback&&noMoreSubscribersCallback();activationState=_stoppedState}};this.unsubscribe=(callback=undefined)=>{const remove=callback?subscribers.filter(sub=>sub.callback===callback):subscribers;remove.forEach(sub=>{const i=subscribers.indexOf(sub);subscribers.splice(i,1)});checkActiveSubscribers()};this.stop=()=>{subscribers.splice(0);checkActiveSubscribers()};const publish=val=>{subscribers.forEach(sub=>{try{sub.callback(val)}catch(err){debug.error(`Error running subscriber callback: ${err.message}`)}});return subscribers.length>0};const start=allSubscriptionsStoppedCallback=>{activationState=true;noMoreSubscribersCallback=allSubscriptionsStoppedCallback;subscribers.forEach(sub=>{sub.activationCallback&&sub.activationCallback(true)})};const cancel=reason=>{activationState=reason;subscribers.forEach(sub=>{sub.activationCallback&&sub.activationCallback(false,reason||new Error("unknown reason"))});subscribers.splice()};const publisher=new EventPublisher(publish,start,cancel);eventPublisherCallback(publisher)}}module.exports={EventStream:EventStream,EventPublisher:EventPublisher,EventSubscription:EventSubscription}},{}],15:[function(require,module,exports){const{PathReference:PathReference}=require("./path-reference");const{cloneObject:cloneObject}=require("./utils");const ascii85=require("./ascii85");module.exports={deserialize(data){if(data.map===null||typeof data.map==="undefined"){return data.val}const deserializeValue=(type,val)=>{if(type==="date"){return new Date(val)}else if(type==="binary"){return ascii85.decode(val)}else if(type==="reference"){return new PathReference(val)}else if(type==="regexp"){return new RegExp(val.pattern,val.flags)}return val};if(typeof data.map==="string"){return deserializeValue(data.map,data.val)}Object.keys(data.map).forEach(path=>{const type=data.map[path];const keys=path.replace(/\[/g,"/[").split("/");keys.forEach((key,index)=>{if(key.startsWith("[")){keys[index]=parseInt(key.substr(1,key.length-2))}});let parent=data;let key="val";let val=data.val;keys.forEach(k=>{key=k;parent=val;val=val[key]});parent[key]=deserializeValue(type,val)});return data.val},serialize(obj){if(obj===null||typeof obj!=="object"||obj instanceof Date||obj instanceof ArrayBuffer||obj instanceof PathReference){const ser=this.serialize({value:obj});return{map:ser.map.value,val:ser.val.value}}obj=cloneObject(obj);const process=(obj,mappings,prefix)=>{Object.keys(obj).forEach(key=>{const val=obj[key];const path=prefix.length===0?key:`${prefix}/${key}`;if(val instanceof Date){obj[key]=val.toISOString();mappings[path]="date"}else if(val instanceof ArrayBuffer){obj[key]=ascii85.encode(val);mappings[path]="binary"}else if(val instanceof PathReference){obj[key]=val.path;mappings[path]="reference"}else if(val instanceof RegExp){obj[key]={pattern:val.source,flags:val.flags};mappings[path]="regexp"}else if(typeof val==="object"&&val!==null){process(val,mappings,path)}})};const mappings={};process(obj,mappings,"");return{map:mappings,val:obj}}}},{"./ascii85":6,"./path-reference":13,"./utils":17}],16:[function(require,module,exports){const{cloneObject:cloneObject}=require("./utils");const{PathInfo:PathInfo}=require("./path-info");const{AceBaseBase:AceBaseBase}=require("./acebase-base");const{DataReference:DataReference}=require("./data-reference");const{DataSnapshot:DataSnapshot}=require("./data-snapshot");const get=(mappings,path)=>{path=path.replace(/^\/|\/$/g,"");const keys=PathInfo.getPathKeys(path);const mappedPath=Object.keys(mappings).find(mpath=>{const mkeys=PathInfo.getPathKeys(mpath);if(mkeys.length!==keys.length){return false}return mkeys.every((mkey,index)=>{if(mkey==="*"||mkey[0]==="$"){return true}return mkey===keys[index]})});const mapping=mappings[mappedPath];return mapping};const map=(mappings,path)=>{const targetPath=PathInfo.get(path).parentPath;if(targetPath===null){return}return get(mappings,targetPath)};const mapDeep=(mappings,entryPath)=>{entryPath=entryPath.replace(/^\/|\/$/g,"");const pathInfo=PathInfo.get(entryPath);const startPath=pathInfo.parentPath;const keys=startPath?PathInfo.getPathKeys(startPath):[];const matches=Object.keys(mappings).reduce((m,mpath)=>{const mkeys=PathInfo.getPathKeys(mpath);if(mkeys.length{if(index>=keys.length){return false}else if(mkey==="*"||mkey[0]==="$"||mkey===keys[index]){return true}else{isMatch=false;return false}})}if(isMatch){const mapping=mappings[mpath];m.push({path:mpath,type:mapping})}return m},[]);return matches};const process=(db,mappings,path,obj,action)=>{if(obj===null||typeof obj!=="object"){return obj}const keys=PathInfo.getPathKeys(path);const m=mapDeep(mappings,path);const changes=[];m.sort((a,b)=>PathInfo.getPathKeys(a.path).length>PathInfo.getPathKeys(b.path).length?-1:1);m.forEach(mapping=>{const mkeys=PathInfo.getPathKeys(mapping.path);mkeys.push("*");const mTrailKeys=mkeys.slice(keys.length);if(mTrailKeys.length===0){const vars=PathInfo.extractVariables(mapping.path,path);const ref=new DataReference(db,path,vars);if(action==="serialize"){obj=mapping.type.serialize(obj,ref)}else if(action==="deserialize"){const snap=new DataSnapshot(ref,obj);obj=mapping.type.deserialize(snap)}return}const process=(parentPath,parent,keys)=>{if(obj===null||typeof obj!=="object"){return obj}const key=keys[0];let children=[];if(key==="*"||key[0]==="$"){if(parent instanceof Array){children=parent.map((val,index)=>({key:index,val:val}))}else{children=Object.keys(parent).map(k=>({key:k,val:parent[k]}))}}else{const child=parent[key];if(typeof child==="object"){children.push({key:key,val:child})}}children.forEach(child=>{const childPath=PathInfo.getChildPath(parentPath,child.key);const vars=PathInfo.extractVariables(mapping.path,childPath);const ref=new DataReference(db,childPath,vars);if(keys.length===1){if(action==="serialize"){changes.push({parent:parent,key:child.key,original:parent[child.key]});parent[child.key]=mapping.type.serialize(child.val,ref)}else if(action==="deserialize"){const snap=new DataSnapshot(ref,child.val);parent[child.key]=mapping.type.deserialize(snap)}}else{process(childPath,child.val,keys.slice(1))}})};process(path,obj,mTrailKeys)});if(action==="serialize"){obj=cloneObject(obj);if(changes.length>0){changes.forEach(change=>{change.parent[change.key]=change.original})}}return obj};class TypeMappingOptions{constructor(options){if(!options){options={}}this.serializer=options.serializer;this.creator=options.creator}}const _mappings=Symbol("mappings");class TypeMappings{constructor(db){this.db=db;this[_mappings]={}}get mappings(){return this[_mappings]}map(path){return map(this[_mappings],path)}bind(path,type,options={}){if(typeof path!=="string"){throw new TypeError("path must be a string")}if(typeof type!=="function"){throw new TypeError("constructor must be a function")}if(typeof options.serializer==="undefined"){}else if(typeof options.serializer==="string"){if(typeof type.prototype[options.serializer]==="function"){options.serializer=type.prototype[options.serializer]}else{throw new TypeError(`${type.name}.prototype.${options.serializer} is not a function, cannot use it as serializer`)}}else if(typeof options.serializer!=="function"){throw new TypeError(`serializer for class ${type.name} must be a function, or the name of a prototype method`)}if(typeof options.creator==="undefined"){if(typeof type.create==="function"){options.creator=type.create}}else if(typeof options.creator==="string"){if(typeof type[options.creator]==="function"){options.creator=type[options.creator]}else{throw new TypeError(`${type.name}.${options.creator} is not a function, cannot use it as creator`)}}else if(typeof options.creator!=="function"){throw new TypeError(`creator for class ${type.name} must be a function, or the name of a static method`)}path=path.replace(/^\/|\/$/g,"");this[_mappings][path]={db:this.db,type:type,creator:options.creator,serializer:options.serializer,deserialize(snap){let obj;if(this.creator){obj=this.creator.call(this.type,snap)}else{obj=new this.type(snap)}return obj},serialize(obj,ref){if(this.serializer){obj=this.serializer.call(obj,ref,obj)}else if(obj&&typeof obj.serialize==="function"){obj=obj.serialize(ref,obj)}return obj}}}serialize(path,obj){return process(this.db,this[_mappings],path,obj,"serialize")}deserialize(path,obj){return process(this.db,this[_mappings],path,obj,"deserialize")}}module.exports={TypeMappings:TypeMappings,TypeMappingOptions:TypeMappingOptions}},{"./acebase-base":4,"./data-reference":7,"./data-snapshot":8,"./path-info":12,"./utils":17}],17:[function(require,module,exports){(function(Buffer){const{PathReference:PathReference}=require("./path-reference");function numberToBytes(number){const bytes=new Uint8Array(8);const view=new DataView(bytes.buffer);view.setFloat64(0,number);return new Array(...bytes)}function bytesToNumber(bytes){if(bytes.length<8){throw new TypeError("must be 8 bytes")}const bin=new Uint8Array(bytes);const view=new DataView(bin.buffer);const nr=view.getFloat64(0);return nr}function encodeString(str){if(typeof TextEncoder!=="undefined"){const encoder=new TextEncoder;return encoder.encode(str)}else if(typeof Buffer==="function"){const buf=Buffer.from(str,"utf-8");return new Uint8Array(buf.buffer,buf.byteOffset,buf.byteLength)}else{let arr=[];for(let i=0;i128){if((code&55296)===55296){const nextCode=str.charCodeAt(i+1);if((nextCode&56320)!==56320){throw new Error("follow-up utf-16 character does not start with 0xDC00")}i++;const p1=code&1023;const p2=nextCode&1023;code=65536|p1<<10|p2}if(code<2048){const b1=192|code>>6&31;const b2=128|code&63;arr.push(b1,b2)}else if(code<65536){const b1=224|code>>12&15;const b2=128|code>>6&63;const b3=128|code&63;arr.push(b1,b2,b3)}else if(code<2097152){const b1=240|code>>18&7;const b2=128|code>>12&63;const b3=128|code>>6&63;const b4=128|code&63;arr.push(b1,b2,b3,b4)}else{throw new Error(`Cannot convert character ${str.charAt(i)} (code ${code}) to utf-8`)}}else{arr.push(code<128?code:63)}}return new Uint8Array(arr)}}function decodeString(buffer){if(typeof TextDecoder!=="undefined"){const decoder=new TextDecoder;if(buffer instanceof Uint8Array){return decoder.decode(buffer)}const buf=Uint8Array.from(buffer);return decoder.decode(buf)}else if(typeof Buffer==="function"){if(buffer instanceof Buffer){return buffer.toString("utf-8")}else if(buffer instanceof Array){const typedArray=Uint8Array.from(buffer);const buf=Buffer.from(typedArray.buffer,typedArray.byteOffset,typedArray.byteOffset+typedArray.byteLength);return buf.toString("utf-8")}else if("buffer"in buffer&&buffer["buffer"]instanceof ArrayBuffer){const buf=Buffer.from(buffer["buffer"],buffer.byteOffset,buffer.byteOffset+buffer.byteLength);return buf.toString("utf-8")}else{throw new Error(`Unsupported buffer argument`)}}else{if(!(buffer instanceof Uint8Array)&&"buffer"in buffer&&buffer["buffer"]instanceof ArrayBuffer){buffer=new Uint8Array(buffer["buffer"],buffer.byteOffset,buffer.byteLength)}if(buffer instanceof Buffer||buffer instanceof Array||buffer instanceof Uint8Array){let str="";for(let i=0;i128){if((code&240)===240){const b1=code,b2=buffer[i+1],b3=buffer[i+2],b4=buffer[i+3];code=(b1&7)<<18|(b2&63)<<12|(b3&63)<<6|b4&63;i+=3}else if((code&224)===224){const b1=code,b2=buffer[i+1],b3=buffer[i+2];code=(b1&15)<<12|(b2&63)<<6|b3&63;i+=2}else if((code&192)===192){const b1=code,b2=buffer[i+1];code=(b1&31)<<6|b2&63;i++}else{throw new Error(`invalid utf-8 data`)}}if(code>=65536){code^=65536;const p1=55296|code>>10;const p2=56320|code&1023;str+=String.fromCharCode(p1);str+=String.fromCharCode(p2)}else{str+=String.fromCharCode(code)}}return str}else{throw new Error(`Unsupported buffer argument`)}}}function concatTypedArrays(a,b){const c=new a.constructor(a.length+b.length);c.set(a);c.set(b,a.length);return c}function cloneObject(original,stack){const{DataSnapshot:DataSnapshot}=require("./data-snapshot");if(original instanceof DataSnapshot){throw new TypeError(`Object to clone is a DataSnapshot (path "${original.ref.path}")`)}const checkAndFixTypedArray=obj=>{if(obj!==null&&typeof obj==="object"&&typeof obj.constructor==="function"&&typeof obj.constructor.name==="string"&&["Buffer","Uint8Array","Int8Array","Uint16Array","Int16Array","Uint32Array","Int32Array","BigUint64Array","BigInt64Array"].includes(obj.constructor.name)){obj=obj.buffer.slice(obj.byteOffset,obj.byteOffset+obj.byteLength)}return obj};original=checkAndFixTypedArray(original);if(typeof original!=="object"||original===null||original instanceof Date||original instanceof ArrayBuffer||original instanceof PathReference||original instanceof RegExp){return original}const cloneValue=val=>{if(stack.indexOf(val)>=0){throw new ReferenceError(`object contains a circular reference`)}val=checkAndFixTypedArray(val);if(val===null||val instanceof Date||val instanceof ArrayBuffer||val instanceof PathReference||val instanceof RegExp){return val}else if(val instanceof Array){stack.push(val);val=val.map(item=>cloneValue(item));stack.pop();return val}else if(typeof val==="object"){stack.push(val);val=cloneObject(val,stack);stack.pop();return val}else{return val}};if(typeof stack==="undefined"){stack=[original]}const clone=original instanceof Array?[]:{};Object.keys(original).forEach(key=>{let val=original[key];if(typeof val==="function"){return}clone[key]=cloneValue(val)});return clone}function compareValues(oldVal,newVal){const voids=[undefined,null];if(oldVal===newVal){return"identical"}else if(voids.indexOf(oldVal)>=0&&voids.indexOf(newVal)<0){return"added"}else if(voids.indexOf(oldVal)<0&&voids.indexOf(newVal)>=0){return"removed"}else if(typeof oldVal!==typeof newVal){return"changed"}else if(typeof oldVal==="object"&&!(oldVal instanceof Date)){const isArray=oldVal instanceof Array;const oldKeys=isArray?Object.keys(oldVal).map(v=>parseInt(v)):Object.keys(oldVal);const newKeys=isArray?Object.keys(newVal).map(v=>parseInt(v)):Object.keys(newVal);const removedKeys=oldKeys.filter(key=>newKeys.indexOf(key)<0);const addedKeys=newKeys.filter(key=>oldKeys.indexOf(key)<0);const changedKeys=newKeys.reduce((changed,key)=>{if(oldKeys.indexOf(key)>=0){const val1=oldVal[key];const val2=newVal[key];const c=compareValues(val1,val2);if(c!=="identical"){changed.push({key:key,change:c})}}return changed},[]);if(addedKeys.length===0&&removedKeys.length===0&&changedKeys.length===0){return"identical"}else{return{added:addedKeys,removed:removedKeys,changed:changedKeys}}}else if(oldVal!==newVal){return"changed"}return"identical"}const getChildValues=(childKey,oldValue,newValue)=>{oldValue=oldValue===null?null:oldValue[childKey];if(typeof oldValue==="undefined"){oldValue=null}newValue=newValue===null?null:newValue[childKey];if(typeof newValue==="undefined"){newValue=null}return{oldValue:oldValue,newValue:newValue}};module.exports={numberToBytes:numberToBytes,bytesToNumber:bytesToNumber,concatTypedArrays:concatTypedArrays,cloneObject:cloneObject,compareValues:compareValues,getChildValues:getChildValues,encodeString:encodeString,decodeString:decodeString}}).call(this,require("buffer").Buffer)},{"./data-snapshot":8,"./path-reference":13,buffer:40}],18:[function(require,module,exports){var colors={};module["exports"]=colors;colors.themes={};var util=require("util");var ansiStyles=colors.styles=require("./styles");var defineProps=Object.defineProperties;var newLineRegex=new RegExp(/[\r\n]+/g);colors.supportsColor=require("./system/supports-colors").supportsColor;if(typeof colors.enabled==="undefined"){colors.enabled=colors.supportsColor()!==false}colors.enable=function(){colors.enabled=true};colors.disable=function(){colors.enabled=false};colors.stripColors=colors.strip=function(str){return(""+str).replace(/\x1B\[\d+m/g,"")};var stylize=colors.stylize=function stylize(str,style){if(!colors.enabled){return str+""}return ansiStyles[style].open+str+ansiStyles[style].close};var matchOperatorsRe=/[|\\{}()[\]^$+*?.]/g;var escapeStringRegexp=function(str){if(typeof str!=="string"){throw new TypeError("Expected a string")}return str.replace(matchOperatorsRe,"\\$&")};function build(_styles){var builder=function builder(){return applyStyle.apply(builder,arguments)};builder._styles=_styles;builder.__proto__=proto;return builder}var styles=function(){var ret={};ansiStyles.grey=ansiStyles.gray;Object.keys(ansiStyles).forEach((function(key){ansiStyles[key].closeRe=new RegExp(escapeStringRegexp(ansiStyles[key].close),"g");ret[key]={get:function(){return build(this._styles.concat(key))}}}));return ret}();var proto=defineProps((function colors(){}),styles);function applyStyle(){var args=Array.prototype.slice.call(arguments);var str=args.map((function(arg){if(arg!=undefined&&arg.constructor===String){return arg}else{return util.inspect(arg)}})).join(" ");if(!colors.enabled||!str){return str}var newLinesPresent=str.indexOf("\n")!=-1;var nestedStyles=this._styles;var i=nestedStyles.length;while(i--){var code=ansiStyles[nestedStyles[i]];str=code.open+str.replace(code.closeRe,code.open)+code.close;if(newLinesPresent){str=str.replace(newLineRegex,(function(match){return code.close+match+code.open}))}}return str}colors.setTheme=function(theme){if(typeof theme==="string"){console.log("colors.setTheme now only accepts an object, not a string. "+"If you are trying to set a theme from a file, it is now your (the "+"caller's) responsibility to require the file. The old syntax "+"looked like colors.setTheme(__dirname + "+"'/../themes/generic-logging.js'); The new syntax looks like "+"colors.setTheme(require(__dirname + "+"'/../themes/generic-logging.js'));");return}for(var style in theme){(function(style){colors[style]=function(str){if(typeof theme[style]==="object"){var out=str;for(var i in theme[style]){out=colors[theme[style][i]](out)}return out}return colors[theme[style]](str)}})(style)}};function init(){var ret={};Object.keys(styles).forEach((function(name){ret[name]={get:function(){return build([name])}}}));return ret}var sequencer=function sequencer(map,str){var exploded=str.split("");exploded=exploded.map(map);return exploded.join("")};colors.trap=require("./custom/trap");colors.zalgo=require("./custom/zalgo");colors.maps={};colors.maps.america=require("./maps/america")(colors);colors.maps.zebra=require("./maps/zebra")(colors);colors.maps.rainbow=require("./maps/rainbow")(colors);colors.maps.random=require("./maps/random")(colors);for(var map in colors.maps){(function(map){colors[map]=function(str){return sequencer(colors.maps[map],str)}})(map)}defineProps(colors,init())},{"./custom/trap":19,"./custom/zalgo":20,"./maps/america":23,"./maps/rainbow":24,"./maps/random":25,"./maps/zebra":26,"./styles":27,"./system/supports-colors":29,util:46}],19:[function(require,module,exports){module["exports"]=function runTheTrap(text,options){var result="";text=text||"Run the trap, drop the bass";text=text.split("");var trap={a:["@","Ą","Ⱥ","Ʌ","Δ","Λ","Д"],b:["ß","Ɓ","Ƀ","ɮ","β","฿"],c:["©","Ȼ","Ͼ"],d:["Ð","Ɗ","Ԁ","ԁ","Ԃ","ԃ"],e:["Ë","ĕ","Ǝ","ɘ","Σ","ξ","Ҽ","੬"],f:["Ӻ"],g:["ɢ"],h:["Ħ","ƕ","Ң","Һ","Ӈ","Ԋ"],i:["༏"],j:["Ĵ"],k:["ĸ","Ҡ","Ӄ","Ԟ"],l:["Ĺ"],m:["ʍ","Ӎ","ӎ","Ԡ","ԡ","൩"],n:["Ñ","ŋ","Ɲ","Ͷ","Π","Ҋ"],o:["Ø","õ","ø","Ǿ","ʘ","Ѻ","ם","۝","๏"],p:["Ƿ","Ҏ"],q:["্"],r:["®","Ʀ","Ȑ","Ɍ","ʀ","Я"],s:["§","Ϟ","ϟ","Ϩ"],t:["Ł","Ŧ","ͳ"],u:["Ʊ","Ս"],v:["ט"],w:["Ш","Ѡ","Ѽ","൰"],x:["Ҳ","Ӿ","Ӽ","ӽ"],y:["¥","Ұ","Ӌ"],z:["Ƶ","ɀ"]};text.forEach((function(c){c=c.toLowerCase();var chars=trap[c]||[" "];var rand=Math.floor(Math.random()*chars.length);if(typeof trap[c]!=="undefined"){result+=trap[c][rand]}else{result+=c}}));return result}},{}],20:[function(require,module,exports){module["exports"]=function zalgo(text,options){text=text||" he is here ";var soul={up:["̍","̎","̄","̅","̿","̑","̆","̐","͒","͗","͑","̇","̈","̊","͂","̓","̈","͊","͋","͌","̃","̂","̌","͐","̀","́","̋","̏","̒","̓","̔","̽","̉","ͣ","ͤ","ͥ","ͦ","ͧ","ͨ","ͩ","ͪ","ͫ","ͬ","ͭ","ͮ","ͯ","̾","͛","͆","̚"],down:["̖","̗","̘","̙","̜","̝","̞","̟","̠","̤","̥","̦","̩","̪","̫","̬","̭","̮","̯","̰","̱","̲","̳","̹","̺","̻","̼","ͅ","͇","͈","͉","͍","͎","͓","͔","͕","͖","͙","͚","̣"],mid:["̕","̛","̀","́","͘","̡","̢","̧","̨","̴","̵","̶","͜","͝","͞","͟","͠","͢","̸","̷","͡"," ҉"]};var all=[].concat(soul.up,soul.down,soul.mid);function randomNumber(range){var r=Math.floor(Math.random()*range);return r}function isChar(character){var bool=false;all.filter((function(i){bool=i===character}));return bool}function heComes(text,options){var result="";var counts;var l;options=options||{};options["up"]=typeof options["up"]!=="undefined"?options["up"]:true;options["mid"]=typeof options["mid"]!=="undefined"?options["mid"]:true;options["down"]=typeof options["down"]!=="undefined"?options["down"]:true;options["size"]=typeof options["size"]!=="undefined"?options["size"]:"maxi";text=text.split("");for(l in text){if(isChar(l)){continue}result=result+text[l];counts={up:0,down:0,mid:0};switch(options.size){case"mini":counts.up=randomNumber(8);counts.mid=randomNumber(2);counts.down=randomNumber(8);break;case"maxi":counts.up=randomNumber(16)+3;counts.mid=randomNumber(4)+1;counts.down=randomNumber(64)+3;break;default:counts.up=randomNumber(8)+1;counts.mid=randomNumber(6)/2;counts.down=randomNumber(8)+1;break}var arr=["up","mid","down"];for(var d in arr){var index=arr[d];for(var i=0;i<=counts[index];i++){if(options[index]){result=result+soul[index][randomNumber(soul[index].length)]}}}}return result}return heComes(text,options)}},{}],21:[function(require,module,exports){var colors=require("./colors");module["exports"]=function(){var addProperty=function(color,func){String.prototype.__defineGetter__(color,func)};addProperty("strip",(function(){return colors.strip(this)}));addProperty("stripColors",(function(){return colors.strip(this)}));addProperty("trap",(function(){return colors.trap(this)}));addProperty("zalgo",(function(){return colors.zalgo(this)}));addProperty("zebra",(function(){return colors.zebra(this)}));addProperty("rainbow",(function(){return colors.rainbow(this)}));addProperty("random",(function(){return colors.random(this)}));addProperty("america",(function(){return colors.america(this)}));var x=Object.keys(colors.styles);x.forEach((function(style){addProperty(style,(function(){return colors.stylize(this,style)}))}));function applyTheme(theme){var stringPrototypeBlacklist=["__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__","charAt","constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf","charCodeAt","indexOf","lastIndexOf","length","localeCompare","match","repeat","replace","search","slice","split","substring","toLocaleLowerCase","toLocaleUpperCase","toLowerCase","toUpperCase","trim","trimLeft","trimRight"];Object.keys(theme).forEach((function(prop){if(stringPrototypeBlacklist.indexOf(prop)!==-1){console.log("warn: ".red+("String.prototype"+prop).magenta+" is probably something you don't want to override. "+"Ignoring style name")}else{if(typeof theme[prop]==="string"){colors[prop]=colors[theme[prop]]}else{var tmp=colors[theme[prop][0]];for(var t=1;t=2,has16m:level>=3}}function supportsColor(stream){if(forceColor===false){return 0}if(hasFlag("color=16m")||hasFlag("color=full")||hasFlag("color=truecolor")){return 3}if(hasFlag("color=256")){return 2}if(stream&&!stream.isTTY&&forceColor!==true){return 0}var min=forceColor?1:0;if(process.platform==="win32"){var osRelease=os.release().split(".");if(Number(process.versions.node.split(".")[0])>=8&&Number(osRelease[0])>=10&&Number(osRelease[2])>=10586){return Number(osRelease[2])>=14931?3:2}return 1}if("CI"in env){if(["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI"].some((function(sign){return sign in env}))||env.CI_NAME==="codeship"){return 1}return min}if("TEAMCITY_VERSION"in env){return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION)?1:0}if("TERM_PROGRAM"in env){var version=parseInt((env.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(env.TERM_PROGRAM){case"iTerm.app":return version>=3?3:2;case"Hyper":return 3;case"Apple_Terminal":return 2}}if(/-256(color)?$/i.test(env.TERM)){return 2}if(/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)){return 1}if("COLORTERM"in env){return 1}if(env.TERM==="dumb"){return min}return min}function getSupportLevel(stream){var level=supportsColor(stream);return translateLevel(level)}module.exports={supportsColor:getSupportLevel,stdout:getSupportLevel(process.stdout),stderr:getSupportLevel(process.stderr)}}).call(this,require("_process"))},{"./has-flag.js":28,_process:44,os:43}],30:[function(require,module,exports){const{AceBase:AceBase,AceBaseLocalSettings:AceBaseLocalSettings}=require("./acebase-local");const{CustomStorageSettings:CustomStorageSettings,CustomStorageTransaction:CustomStorageTransaction,CustomStorageHelpers:CustomStorageHelpers,ICustomStorageNode:ICustomStorageNode,ICustomStorageNodeMetaData:ICustomStorageNodeMetaData}=require("./storage-custom");const deprecatedConstructorError=`Using AceBase constructor in the browser to use localStorage is deprecated!\nSwitch to:\nIndexedDB implementation (FASTER, MORE RELIABLE):\n let db = AceBase.WithIndexedDB(name, settings)\nOr, new LocalStorage implementation:\n let db = AceBase.WithLocalStorage(name, settings)\nOr, write your own CustomStorage adapter:\n let myCustomStorage = new CustomStorageSettings({ ... });\n let db = new AceBase(name, { storage: myCustomStorage })`;class BrowserAceBase extends AceBase{constructor(name,settings){if(typeof settings!=="object"||typeof settings.storage!=="object"){throw new Error(deprecatedConstructorError)}super(name,settings)}static WithIndexedDB(dbname,settings){settings=settings||{};if(!settings.logLevel){settings.logLevel="error"}const IndexedDB=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB;let request=IndexedDB.open(`${dbname}.acebase`,1);let readyResolve,readyReject,readyPromise=new Promise((rs,rj)=>{readyResolve=rs;readyReject=rj});request.onupgradeneeded=e=>{let db=request.result;db.createObjectStore("nodes",{keyPath:"path"});db.createObjectStore("content")};let db;request.onsuccess=e=>{db=request.result;readyResolve()};request.onerror=e=>{readyReject(e)};const storageSettings=new CustomStorageSettings({name:"IndexedDB",locking:true,ready(){return readyPromise},async getTransaction(target){await readyPromise;const context={debug:true,db:db};return new IndexedDBStorageTransaction(context,target)}});return new AceBase(dbname,{logLevel:settings.logLevel,storage:storageSettings})}}function _requestToPromise(request){return new Promise((resolve,reject)=>{request.onsuccess=event=>{return resolve(request.result||null)};request.onerror=reject})}class IndexedDBStorageTransaction extends CustomStorageTransaction{constructor(context,target){super(target);this.context=context;this._pending=[]}_createTransaction(write=false){const tx=this.context.db.transaction(["nodes","content"],write?"readwrite":"readonly");return tx}commit(){if(this._pending.length===0){return Promise.resolve()}const ops=this._pending.splice(0);const tx=this._createTransaction(true);const promises=ops.map(op=>{if(op.action==="set"){return this._set(tx,op.path,op.node)}else if(op.action==="remove"){return this._remove(tx,op.path)}else{throw new Error("Unknown pending operation")}});return Promise.all(promises).then(()=>{tx.commit&&tx.commit()}).catch(err=>{console.error(err);tx.abort&&tx.abort()})}rollback(err){this._pending=[];return Promise.resolve()}get(path){const tx=this._createTransaction(false);const r1=_requestToPromise(tx.objectStore("nodes").get(path));const r2=_requestToPromise(tx.objectStore("content").get(path));return Promise.all([r1,r2]).then(results=>{tx.commit&&tx.commit();const info=results[0];if(!info){return null}const node=info.metadata;node.value=results[1];return node}).catch(err=>{tx.abort&&tx.abort();console.error(`IndexedDB get error`,err);throw err})}set(path,node){this._pending.push({action:"set",path:path,node:node});return Promise.resolve()}remove(path){this._pending.push({action:"remove",path:path});return Promise.resolve()}_set(tx,path,node){const copy={};const value=node.value;Object.assign(copy,node);delete copy.value;const metadata=copy;const obj={path:path,metadata:metadata};const r1=_requestToPromise(tx.objectStore("nodes").put(obj));const r2=_requestToPromise(tx.objectStore("content").put(value,path));return Promise.all([r1,r2])}_remove(tx,path){const r1=_requestToPromise(tx.objectStore("content").delete(path));const r2=_requestToPromise(tx.objectStore("nodes").delete(path));return Promise.all([r1,r2])}childrenOf(path,include,checkCallback,addCallback){return new Promise((resolve,reject)=>{const pathInfo=CustomStorageHelpers.PathInfo.get(path);const tx=this._createTransaction(false);const store=tx.objectStore("nodes");const query=IDBKeyRange.lowerBound(path,true);const cursor=include.metadata?store.openCursor(query):store.openKeyCursor(query);cursor.onerror=e=>{tx.abort&&tx.abort();reject(e)};cursor.onsuccess=async e=>{const otherPath=cursor.result?cursor.result.key:null;let keepGoing=true;if(otherPath===null){keepGoing=false}else if(!pathInfo.isAncestorOf(otherPath)){keepGoing=false}else if(pathInfo.isParentOf(otherPath)&&checkCallback(otherPath)){let node;if(include.metadata){const valueCursor=cursor;const data=valueCursor.result.value;node=data.metadata;if(include.value){const req=tx.objectStore("content").get(otherPath);node.value=await new Promise((resolve,reject)=>{req.onerror=e=>{resolve(null)};req.onsuccess=e=>{resolve(req.result)}})}}keepGoing=addCallback(otherPath,node)}if(keepGoing){try{cursor.result.continue()}catch(err){keepGoing=false}}if(!keepGoing){tx.commit&&tx.commit();resolve()}}})}descendantsOf(path,include,checkCallback,addCallback){return new Promise((resolve,reject)=>{const pathInfo=CustomStorageHelpers.PathInfo.get(path);const tx=this._createTransaction(false);const store=tx.objectStore("nodes");const query=IDBKeyRange.lowerBound(path,true);const cursor=include.metadata?store.openCursor(query):store.openKeyCursor(query);cursor.onerror=e=>{tx.abort&&tx.abort();reject(e)};cursor.onsuccess=async e=>{const otherPath=cursor.result?cursor.result.key:null;let keepGoing=true;if(otherPath===null){keepGoing=false}else if(!pathInfo.isAncestorOf(otherPath)){keepGoing=false}else if(checkCallback(otherPath)){let node;if(include.metadata){const valueCursor=cursor;const data=valueCursor.result.value;node=data.metadata;if(include.value){const req=tx.objectStore("content").get(otherPath);node.value=await new Promise((resolve,reject)=>{req.onerror=e=>{resolve(null)};req.onsuccess=e=>{resolve(req.result)}})}}keepGoing=addCallback(otherPath,node)}if(keepGoing){try{cursor.result.continue()}catch(err){keepGoing=false}}if(!keepGoing){tx.commit&&tx.commit();resolve()}}})}}module.exports={BrowserAceBase:BrowserAceBase}},{"./acebase-local":31,"./storage-custom":38}],31:[function(require,module,exports){const{AceBaseBase:AceBaseBase,AceBaseSettings:AceBaseSettings}=require("acebase-core");const{StorageSettings:StorageSettings}=require("./storage");const{LocalApi:LocalApi}=require("./api-local");const{CustomStorageSettings:CustomStorageSettings,CustomStorageTransaction:CustomStorageTransaction,CustomStorageHelpers:CustomStorageHelpers,ICustomStorageNode:ICustomStorageNode,ICustomStorageNodeMetaData:ICustomStorageNodeMetaData}=require("./storage-custom");class AceBaseLocalSettings{constructor(options){if(!options){options={}}this.logLevel=options.logLevel||"log";this.storage=options.storage}}class AceBase extends AceBaseBase{constructor(dbname,options){options=new AceBaseLocalSettings(options);super(dbname,options);const apiSettings={db:this,storage:options.storage,logLevel:options.logLevel};this.api=new LocalApi(dbname,apiSettings,ready=>{this.emit("ready")})}static WithLocalStorage(dbname,settings){settings=settings||{};if(!settings.logLevel){settings.logLevel="error"}const localStorage=settings.provider?settings.provider:settings.temp?window.localStorage:window.sessionStorage;const storageSettings=new CustomStorageSettings({name:"LocalStorage",locking:true,ready(){return Promise.resolve()},getTransaction(target){const context={debug:true,dbname:dbname,localStorage:localStorage};const transaction=new LocalStorageTransaction(context,target);return Promise.resolve(transaction)}});return new AceBase(dbname,{logLevel:settings.logLevel,storage:storageSettings})}}class LocalStorageTransaction extends CustomStorageTransaction{constructor(context,target){super(target);this.context=context;this._storageKeysPrefix=`${this.context.dbname}.acebase::`}commit(){return Promise.resolve()}rollback(err){return Promise.resolve()}get(path){return new Promise(resolve=>{const json=this.context.localStorage.getItem(this.getStorageKeyForPath(path));const val=JSON.parse(json);resolve(val)})}set(path,val){return new Promise(resolve=>{const json=JSON.stringify(val);this.context.localStorage.setItem(this.getStorageKeyForPath(path),json);resolve()})}remove(path){return new Promise(resolve=>{this.context.localStorage.removeItem(this.getStorageKeyForPath(path));resolve()})}childrenOf(path,include,checkCallback,addCallback){return new Promise(resolve=>{const pathInfo=CustomStorageHelpers.PathInfo.get(path);for(let i=0;i{const pathInfo=CustomStorageHelpers.PathInfo.get(path);for(let i=0;i{}}){if(typeof options!=="object"){options={}}if(typeof options.snapshots==="undefined"){options.snapshots=false}const sortMatches=matches=>{matches.sort((a,b)=>{const compare=i=>{const o=query.order[i];let left=a.val[o.key];let right=b.val[o.key];if(typeof left==="undefined"&&typeof right!=="undefined"){return o.ascending?-1:1}if(typeof left!=="undefined"&&typeof right==="undefined"){return o.ascending?1:-1}if(typeof left==="undefined"&&typeof right==="undefined"){return 0}if(left==right){if(iright){return o.ascending?1:-1}};return compare(0)})};const loadResultsData=(preResults,options)=>{if(preResults.length===0){return Promise.resolve([])}const maxBatchSize=50;let batches=[];const items=preResults.map((result,index)=>({path:result.path,index:index}));while(items.length>0){let batchItems=items.splice(0,maxBatchSize);batches.push(batchItems)}const results=[];const nextBatch=()=>{const batch=batches.shift();return Promise.all(batch.map(item=>{const{path:path,index:index}=item;return Node.getValue(this.storage,path,options).then(val=>{if(val===null){this.storage.debug.warn(`Indexed result "/${path}" does not have a record!`);return}const result={path:path,val:val};if(stepsExecuted.sorted){results[index]=result}else{results.push(result);if(!stepsExecuted.skipped&&results.length>query.skip+query.take){sortMatches(results);results.pop()}}})})).then(()=>{if(batches.length>0){return nextBatch()}})};return nextBatch().then(()=>{return results})};const isWildcardPath=path.includes("*");const availableIndexes=this.storage.indexes.get(path);const usingIndexes=[];query.filters.forEach(filter=>{if(filter.index){return}const indexesOnKey=availableIndexes.filter(index=>index.key===filter.key).filter(index=>{return index.validOperators.includes(filter.op)});if(indexesOnKey.length>=1){const otherFilterKeys=query.filters.filter(f=>f!==filter).map(f=>f.key);const sortKeys=query.order.map(o=>o.key).filter(key=>key!==filter.key);const beneficialIndexes=indexesOnKey.map(index=>{const availableKeys=index.includeKeys.concat(index.key);const forOtherFilters=availableKeys.filter(key=>otherFilterKeys.indexOf(key)>=0);const forSorting=availableKeys.filter(key=>sortKeys.indexOf(key)>=0);const forBoth=forOtherFilters.concat(forSorting.filter(index=>forOtherFilters.indexOf(index)<0));const points={filters:forOtherFilters.length,sorting:forSorting.length*(query.take>0?forSorting.length:1),both:forBoth.length*forBoth.length,get total(){return this.filters+this.sorting+this.both}};return{index:index,points:points.total,filterKeys:forOtherFilters,sortKeys:forSorting}});beneficialIndexes.sort((a,b)=>a.points>b.points?-1:1);const bestBenificialIndex=beneficialIndexes[0];filter.index=bestBenificialIndex.index;bestBenificialIndex.filterKeys.forEach(key=>{query.filters.filter(f=>f!==filter&&f.key===key).forEach(f=>{if(!DataIndex.validOperators.includes(f.op)){return}f.indexUsage="filter";f.index=bestBenificialIndex.index})});bestBenificialIndex.sortKeys.forEach(key=>{query.order.filter(s=>s.key===key).forEach(s=>{s.index=bestBenificialIndex.index})})}if(filter.index){usingIndexes.push({index:filter.index,description:filter.index.description})}});if(query.order.length>0&&query.take>0){query.order.forEach(sort=>{if(sort.index){return}sort.index=availableIndexes.filter(index=>index.key===sort.key).find(index=>index.type==="normal")})}const indexDescriptions=usingIndexes.map(index=>index.description).join(", ");usingIndexes.length>0&&this.storage.debug.log(`Using indexes for query: ${indexDescriptions}`);const tableScanFilters=query.filters.filter(filter=>!filter.index);const specialOpsRegex=/^[a-z]+\:/i;if(tableScanFilters.some(filter=>specialOpsRegex.test(filter.op))){const f=tableScanFilters.find(filter=>specialOpsRegex.test(filter.op));const err=new Error(`query contains operator "${f.op}" which requires a special index that was not found on path "${path}", key "${f.key}"`);return Promise.reject(err)}const allowedTableScanOperators=["<","<=","==","!=",">=",">","like","!like","in","!in","matches","!matches","between","!between","has","!has","contains","!contains","exists","!exists"];for(let i=0;i0){const keys=tableScanFilters.reduce((keys,f)=>{if(keys.indexOf(f.key)<0){keys.push(f.key)}return keys},[]).map(key=>`"${key}"`);const err=new Error(`This wildcard path query on "/${path}" requires index(es) on key(s): ${keys.join(", ")}. Create the index(es) and retry`);return Promise.reject(err)}const indexScanPromises=[];query.filters.forEach(filter=>{if(filter.index&&filter.indexUsage!=="filter"){let promise=filter.index.query(filter.op,filter.compare).then(results=>{options.eventHandler&&options.eventHandler({name:"stats",type:"index_query",source:filter.index.description,stats:results.stats});if(results.hints.length>0){options.eventHandler&&options.eventHandler({name:"hints",type:"index_query",source:filter.index.description,hints:results.hints})}return results});const resultFilters=query.filters.filter(f=>f.index===filter.index&&f.indexUsage==="filter");if(resultFilters.length>0){promise=promise.then(results=>{resultFilters.forEach(filter=>{results=results.filterMetadata(filter.key,filter.op,filter.compare)});return results})}indexScanPromises.push(promise)}});const stepsExecuted={filtered:query.filters.length===0,skipped:query.skip===0,taken:query.take===0,sorted:query.order.length===0,preDataLoaded:false,dataLoaded:false};if(query.filters.length===0&&query.take===0){this.storage.debug.error(`Filterless queries must use .take to limit the results. Defaulting to 100 for query on path "${path}"`);query.take=100}if(query.filters.length===0&&query.order.length>0&&query.order[0].index){const sortIndex=query.order[0].index;this.storage.debug.log(`Using index for sorting: ${sortIndex.description}`);const promise=sortIndex.take(query.skip,query.take,query.order[0].ascending).then(results=>{options.eventHandler&&options.eventHandler({name:"stats",type:"sort_index_take",source:filter.index.description,stats:results.stats});if(results.hints.length>0){options.eventHandler&&options.eventHandler({name:"hints",type:"sort_index_take",source:filter.index.description,hints:results.hints})}return results});indexScanPromises.push(promise);stepsExecuted.skipped=true;stepsExecuted.taken=true;stepsExecuted.sorted=true}return Promise.all(indexScanPromises).then(indexResultSets=>{let indexedResults=[];if(indexResultSets.length===1){const resultSet=indexResultSets[0];indexedResults=resultSet.map(match=>{const result={key:match.key,path:match.path,val:{[resultSet.filterKey]:match.value}};match.metadata&&Object.assign(result.val,match.metadata);return result});stepsExecuted.filtered=true}else if(indexResultSets.length>1){indexResultSets.sort((a,b)=>a.length{const result={key:match.key,path:match.path,val:{[shortestSet.filterKey]:match.value}};const matchedInAllSets=otherSets.every(set=>set.findIndex(m=>match.path===match.path)>=0);if(matchedInAllSets){match.metadata&&Object.assign(result.val,match.metadata);otherSets.forEach(set=>{const otherResult=set.find(r=>r.path===result.path);result.val[set.filterKey]=otherResult.value;otherResult.metadata&&Object.assign(result.val,otherResult.metadata)});results.push(result)}return results},[]);stepsExecuted.filtered=true}if(isWildcardPath||indexScanPromises.length>0&&tableScanFilters.length===0){if(query.order.length===0||query.order.every(o=>o.index)){stepsExecuted.preDataLoaded=true;if(!stepsExecuted.sorted&&query.order.length>0){sortMatches(indexedResults)}stepsExecuted.sorted=true;if(!stepsExecuted.skipped&&query.skip>0){indexedResults=indexedResults.slice(query.skip)}if(!stepsExecuted.taken&&query.take>0){indexedResults=indexedResults.slice(0,query.take)}stepsExecuted.skipped=true;stepsExecuted.taken=true;if(!options.snapshots){return indexedResults}const childOptions={include:options.include,exclude:options.exclude,child_objects:options.child_objects};return loadResultsData(indexedResults,childOptions).then(results=>{stepsExecuted.dataLoaded=true;return results})}if(options.snapshots||!stepsExecuted.sorted){const loadPartialResults=query.order.length>0;const childOptions=loadPartialResults?{include:query.order.map(order=>order.key)}:{include:options.include,exclude:options.exclude,child_objects:options.child_objects};return loadResultsData(indexedResults,childOptions).then(results=>{if(query.order.length>0){sortMatches(results)}stepsExecuted.sorted=true;if(query.skip>0){results=results.slice(query.skip)}if(query.take>0){results=results.slice(0,query.take)}stepsExecuted.skipped=true;stepsExecuted.taken=true;if(options.snapshots&&loadPartialResults){return loadResultsData(results,{include:options.include,exclude:options.exclude,child_objects:options.child_objects})}return results})}else{return indexedResults}}let indexKeyFilter;if(indexedResults.length>0){indexKeyFilter=indexedResults.map(result=>result.key)}const promises=[];let matches=[];let preliminaryStop=false;const loadPartialData=query.order.length>0;const childOptions=loadPartialData?{include:query.order.map(order=>order.key)}:{include:options.include,exclude:options.exclude,child_objects:options.child_objects};return Node.getChildren(this.storage,path,indexKeyFilter).next(child=>{if(child.type===Node.VALUE_TYPES.OBJECT){if(!child.address){return}if(preliminaryStop){return false}const p=Node.matches(this.storage,child.address.path,tableScanFilters).then(isMatch=>{if(!isMatch){return null}const childPath=child.address.path;if(options.snapshots||query.order.length>0){return Node.getValue(this.storage,childPath,childOptions).then(val=>{return{path:childPath,val:val}})}else{return{path:childPath}}}).then(result=>{if(result!==null){matches.push(result);if(query.take>0&&matches.length>query.take+query.skip){if(query.order.length>0){sortMatches(matches)}else{preliminaryStop=true}matches.pop()}}});promises.push(p)}}).catch(reason=>{this.storage.debug.warn(`Error getting child stream: ${reason}`);return[]}).then(()=>{return Promise.all(promises).then(()=>{stepsExecuted.preDataLoaded=loadPartialData;stepsExecuted.dataLoaded=!loadPartialData;if(query.order.length>0){sortMatches(matches)}stepsExecuted.sorted=true;if(query.skip>0){matches=matches.slice(query.skip)}stepsExecuted.skipped=true;if(query.take>0){matches=matches.slice(0,query.take)}stepsExecuted.taken=true;if(!stepsExecuted.dataLoaded){return loadResultsData(matches,{include:options.include,exclude:options.exclude,child_objects:options.child_objects}).then(results=>{stepsExecuted.dataLoaded=true;return results})}return matches})})}).then(matches=>{if(!stepsExecuted.sorted&&query.order.length>0){sortMatches(matches)}if(!options.snapshots){matches=matches.map(match=>match.path)}if(!stepsExecuted.skipped&&query.skip>0){matches=matches.slice(query.skip)}if(!stepsExecuted.taken&&query.take>0){matches=matches.slice(0,query.take)}if(options.monitor===true){options.monitor={add:true,change:true,remove:true}}if(typeof options.monitor==="object"&&(options.monitor.add||options.monitor.change||options.monitor.remove)){const matchedPaths=options.snapshots?matches.map(match=>match.path):matches.slice();const ref=this.db.ref(path);const removeMatch=path=>{const index=matchedPaths.indexOf(path);if(index<0){return}matchedPaths.splice(index,1)};const addMatch=path=>{if(matchedPaths.includes(path)){return}matchedPaths.push(path)};const stopMonitoring=()=>{this.unsubscribe(ref.path,"notify_child_changed",childChangedCallback);this.unsubscribe(ref.path,"notify_child_added",childAddedCallback);this.unsubscribe(ref.path,"notify_child_removed",childRemovedCallback)};const childChangedCallback=(err,path,newValue,oldValue)=>{const wasMatch=matchedPaths.includes(path);let keepMonitoring=true;const checkKeys=[];query.filters.forEach(f=>!checkKeys.includes(f.key)&&checkKeys.push(f.key));const seenKeys=[];typeof oldValue==="object"&&Object.keys(oldValue).forEach(key=>!seenKeys.includes(key)&&seenKeys.push(key));typeof newValue==="object"&&Object.keys(newValue).forEach(key=>!seenKeys.includes(key)&&seenKeys.push(key));const missingKeys=[];let isMatch=seenKeys.every(key=>{if(!checkKeys.includes(key)){return true}const filters=query.filters.filter(filter=>filter.key===key);return filters.every(filter=>{if(allowedTableScanOperators.includes(filter.op)){return this.storage.test(newValue[key],filter.op,filter.compare)}if(filter.index.constructor.name==="FullTextDataIndex"&&filter.index.localeKey&&!seenKeys.includes(filter.index.localeKey)){missingKeys.push(filter.index.localeKey);return true}return filter.index.test(newValue,filter.op,filter.compare)})});if(isMatch){missingKeys.push(...checkKeys.filter(key=>!seenKeys.includes(key)));let promise=Promise.resolve(true);if(!wasMatch&&missingKeys.length>0){const filterQueue=query.filters.filter(f=>missingKeys.includes(f.key));const simpleFilters=filterQueue.filter(f=>allowedTableScanOperators.includes(f.op));const indexFilters=filterQueue.filter(f=>!allowedTableScanOperators.includes(f.op));const processFilters=()=>{const checkIndexFilters=()=>{const keysToLoad=indexFilters.reduce((keys,filter)=>{if(!keys.includes(filter.key)){keys.push(filter.key)}if(filter.index.constructor.name==="FullTextDataIndex"&&filter.index.localeKey&&!keys.includes(filter.index.localeKey)){keys.push(filter.index.localeKey)}return keys},[]);return Node.getValue(this.storage,path,{include:keysToLoad}).then(val=>{if(val===null){return false}return indexFilters.every(filter=>filter.index.test(val,filter.op,filter.compare))})};if(simpleFilters.length>0){return Node.matches(this.storage,path,simpleFilters).then(isMatch=>{if(isMatch){if(indexFilters.length===0){return true}return checkIndexFilters()}return false})}else{return checkIndexFilters()}};promise=processFilters()}return promise.then(isMatch=>{if(isMatch){if(!wasMatch){addMatch(path)}let gotValue=value=>{if(wasMatch&&options.monitor.change){keepMonitoring=options.eventHandler({name:"change",path:path,value:value})}else if(!wasMatch&&options.monitor.add){keepMonitoring=options.eventHandler({name:"add",path:path,value:value})}if(keepMonitoring===false){stopMonitoring()}};if(options.snapshots){const loadOptions={include:options.include,exclude:options.exclude,child_objects:options.child_objects};return this.storage.getNodeValue(path,loadOptions).then(gotValue)}else{return gotValue(newValue)}}else if(wasMatch){removeMatch(path);if(options.monitor.remove){keepMonitoring=options.eventHandler({name:"remove",path:path,value:oldValue})}}if(keepMonitoring===false){stopMonitoring()}})}else{if(wasMatch){removeMatch(path);if(options.monitor.remove){keepMonitoring=options.eventHandler({name:"remove",path:path,value:oldValue});if(keepMonitoring===false){stopMonitoring()}}}}};const childAddedCallback=(err,path,newValue,oldValue)=>{let isMatch=query.filters.every(filter=>{if(allowedTableScanOperators.includes(filter.op)){return this.storage.test(newValue[filter.key],filter.op,filter.compare)}else{return filter.index.test(newValue,filter.op,filter.compare)}});let keepMonitoring=true;if(isMatch){addMatch(path);if(options.monitor.add){keepMonitoring=options.eventHandler({name:"add",path:path,value:options.snapshots?newValue:null})}}if(keepMonitoring===false){stopMonitoring()}};const childRemovedCallback=(err,path,newValue,oldValue)=>{let keepMonitoring=true;removeMatch(path);if(options.monitor.remove){keepMonitoring=options.eventHandler({name:"remove",path:path,value:options.snapshots?oldValue:null})}if(keepMonitoring===false){stopMonitoring()}};if(options.monitor.add||options.monitor.change||options.monitor.remove){this.subscribe(ref.path,"notify_child_changed",childChangedCallback)}if(options.monitor.remove){this.subscribe(ref.path,"notify_child_removed",childRemovedCallback)}if(options.monitor.add){this.subscribe(ref.path,"notify_child_added",childAddedCallback)}}return matches})}createIndex(path,key,options){return this.storage.indexes.create(path,key,options)}getIndexes(){return Promise.resolve(this.storage.indexes.list())}reflect(path,type,args){const getChildren=(path,limit=50,skip=0)=>{if(typeof limit==="string"){limit=parseInt(limit)}if(typeof skip==="string"){skip=parseInt(skip)}const children=[];let n=0,stop=skip+limit;return Node.getChildren(this.storage,path).next(childInfo=>{n++;if(limit===0||n<=stop&&n>skip){children.push({key:typeof childInfo.key==="string"?childInfo.key:childInfo.index,type:childInfo.valueTypeName,value:childInfo.value,address:typeof childInfo.address==="object"&&"pageNr"in childInfo.address?{pageNr:childInfo.address.pageNr,recordNr:childInfo.address.recordNr}:undefined})}if(limit>0&&n>stop){return false}}).then(()=>{return{more:limit!==0&&n>stop,list:children}})};switch(type){case"children":{return getChildren(path,args.limit,args.skip)}case"info":{const info={key:"",exists:false,type:"unknown",value:undefined,children:{more:false,list:[]}};return Node.getInfo(this.storage,path).then(nodeInfo=>{info.key=nodeInfo.key;info.exists=nodeInfo.exists;info.type=nodeInfo.valueTypeName;info.value=nodeInfo.value;let hasChildren=nodeInfo.exists&&nodeInfo.address&&[Node.VALUE_TYPES.OBJECT,Node.VALUE_TYPES.ARRAY].includes(nodeInfo.type);if(hasChildren){return getChildren(path,args.child_limit,args.child_skip)}}).then(children=>{info.children=children;return info})}}}export(path,stream,options={format:"json"}){return this.storage.exportNode(path,stream,options)}}module.exports={LocalApi:LocalApi}},{"./acebase-local":31,"./data-index":40,"./node":37,"./storage":39,"./storage-acebase":40,"./storage-custom":38,"./storage-mssql":40,"./storage-sqlite":40,"acebase-core":11}],33:[function(require,module,exports){const{DataReference:DataReference,DataSnapshot:DataSnapshot,EventSubscription:EventSubscription,PathReference:PathReference,TypeMappings:TypeMappings,TypeMappingOptions:TypeMappingOptions}=require("acebase-core");const{AceBaseLocalSettings:AceBaseLocalSettings}=require("./acebase-local");const{BrowserAceBase:BrowserAceBase}=require("./acebase-browser");const{CustomStorageSettings:CustomStorageSettings,CustomStorageTransaction:CustomStorageTransaction,CustomStorageHelpers:CustomStorageHelpers}=require("./storage-custom");const acebase={AceBase:BrowserAceBase,AceBaseLocalSettings:AceBaseLocalSettings,DataReference:DataReference,DataSnapshot:DataSnapshot,EventSubscription:EventSubscription,PathReference:PathReference,TypeMappings:TypeMappings,TypeMappingOptions:TypeMappingOptions,CustomStorageSettings:CustomStorageSettings,CustomStorageTransaction:CustomStorageTransaction,CustomStorageHelpers:CustomStorageHelpers};window.acebase=acebase;window.AceBase=BrowserAceBase;module.exports=acebase},{"./acebase-browser":30,"./acebase-local":31,"./storage-custom":38,"acebase-core":11}],34:[function(require,module,exports){const{VALUE_TYPES:VALUE_TYPES,getValueTypeName:getValueTypeName}=require("./node-value-types");const{PathInfo:PathInfo}=require("acebase-core");class NodeInfo{constructor(info){this.path=info.path;this.type=info.type;this.index=info.index;this.key=info.key;this.exists=info.exists;this.address=info.address;this.value=info.value;if(typeof this.path==="string"&&(typeof this.key==="undefined"&&typeof this.index==="undefined")){let pathInfo=PathInfo.get(this.path);if(typeof pathInfo.key==="number"){this.index=pathInfo.key}else{this.key=pathInfo.key}}if(typeof this.exists==="undefined"){this.exists=true}}get valueType(){return this.type}get valueTypeName(){return getValueTypeName(this.valueType)}toString(){if(!this.exists){return`"${this.path}" doesn't exist`}if(this.address){return`"${this.path}" is ${this.valueTypeName} stored at ${this.address.pageNr},${this.address.recordNr}`}else{return`"${this.path}" is ${this.valueTypeName} with value ${this.value}`}}}module.exports={NodeInfo:NodeInfo}},{"./node-value-types":36,"acebase-core":11}],35:[function(require,module,exports){const{PathInfo:PathInfo}=require("acebase-core");const SECOND=1e3;const MINUTE=6e4;const DEBUG_MODE=false;const LOCK_TIMEOUT=DEBUG_MODE?15*MINUTE:90*SECOND;const LOCK_STATE={PENDING:"pending",LOCKED:"locked",EXPIRED:"expired",DONE:"done"};class NodeLocker{constructor(){this._locks=[]}_allowLock(path,tid,forWriting){const pathInfo=PathInfo.get(path);const existing=this._locks.find(otherLock=>otherLock.tid===tid&&otherLock.state===LOCK_STATE.LOCKED&&(otherLock.path===path||pathInfo.isDescendantOf(otherLock.path))&&(otherLock.forWriting||!forWriting));if(typeof existing==="object"){return{allow:true}}const conflict=this._locks.filter(otherLock=>otherLock.tid!==tid&&otherLock.state===LOCK_STATE.LOCKED).find(otherLock=>{return(forWriting||otherLock.forWriting)&&(path===otherLock.path||pathInfo.isDescendantOf(otherLock.path))});const clashes=typeof conflict!=="undefined";return{allow:!clashes,conflict:conflict}}_processLockQueue(){const pending=this._locks.filter(lock=>lock.state===LOCK_STATE.PENDING&&(lock.waitingFor===null||lock.waitingFor.state!==LOCK_STATE.LOCKED)).sort((a,b)=>{if(a.priority&&!b.priority){return-1}else if(!a.priority&&b.priority){return 1}return a.requested{const check=this._allowLock(lock.path,lock.tid,lock.forWriting);lock.waitingFor=check.conflict||null;if(check.allow){this.lock(lock).then(lock.resolve).catch(lock.reject)}})}lock(path,tid,forWriting=true,comment="",options={withPriority:false,noTimeout:false}){let lock,proceed;if(path instanceof NodeLock){lock=path;lock.comment=`(retry: ${lock.comment})`;proceed=true}else if(this._locks.findIndex(l=>l.tid===tid&&l.state===LOCK_STATE.EXPIRED)>=0){return Promise.reject(new Error(`lock on tid ${tid} has expired, not allowed to continue`))}else{lock=new NodeLock(this,path,tid,forWriting,options.withPriority===true);lock.comment=comment;this._locks.push(lock);const check=this._allowLock(path,tid,forWriting);lock.waitingFor=check.conflict||null;proceed=check.allow}if(proceed){lock.state=LOCK_STATE.LOCKED;if(typeof lock.granted==="number"){}else{lock.granted=Date.now();if(options.noTimeout!==true){lock.expires=Date.now()+LOCK_TIMEOUT;lock.timeout=setTimeout(()=>{if(lock.state!==LOCK_STATE.LOCKED){return}console.error(`lock :: ${lock.forWriting?"write":"read"} lock on path "/${lock.path}" by tid ${lock.tid} took too long, ${lock.comment}`);lock.state=LOCK_STATE.EXPIRED;this._processLockQueue()},LOCK_TIMEOUT)}}return Promise.resolve(lock)}else{console.assert(lock.state===LOCK_STATE.PENDING);const p=new Promise((resolve,reject)=>{lock.resolve=resolve;lock.reject=reject});return p}}unlock(lockOrId,comment,processQueue=true){let lock,i;if(lockOrId instanceof NodeLock){lock=lockOrId;i=this._locks.indexOf(lock)}else{let id=lockOrId;i=this._locks.findIndex(l=>l.id===id);lock=this._locks[i]}if(i<0){const msg=`lock on "/${lock.path}" for tid ${lock.tid} wasn't found; ${comment}`;return Promise.reject(new Error(msg))}lock.state=LOCK_STATE.DONE;clearTimeout(lock.timeout);this._locks.splice(i,1);processQueue&&this._processLockQueue();return Promise.resolve(lock)}list(){return this._locks||[]}isAllowed(path,tid,forWriting){return this._allowLock(path,tid,forWriting).allow}}let lastid=0;class NodeLock{static get LOCK_STATE(){return LOCK_STATE}constructor(locker,path,tid,forWriting,priority=false){this.locker=locker;this.path=path;this.tid=tid;this.forWriting=forWriting;this.priority=priority;this.state=LOCK_STATE.PENDING;this.requested=Date.now();this.granted=undefined;this.expires=undefined;this.comment="";this.waitingFor=null;this.id=++lastid}release(comment){return this.locker.unlock(this,comment||this.comment)}moveToParent(){const parentPath=PathInfo.get(this.path).parentPath;const allowed=this.locker.isAllowed(parentPath,this.tid,this.forWriting);if(allowed){this.waitingFor=null;this.path=parentPath;this.comment=`moved to parent: ${this.comment}`;return Promise.resolve(this)}else{this.locker.unlock(this,`moveLockToParent: ${this.comment}`,false);return this.locker.lock(parentPath,this.tid,this.forWriting,`moved to parent (queued): ${this.comment}`,{withPriority:true}).then(newLock=>{return newLock})}}moveTo(otherPath,forWriting){const allowed=this.locker.isAllowed(otherPath,this.tid,forWriting);if(allowed){this.waitingFor=null;this.path=otherPath;this.forWriting=forWriting;this.comment=`moved to "/${otherPath}": ${this.comment}`;return Promise.resolve(this)}else{this.locker.unlock(this,`moving to "/${otherPath}": ${this.comment}`,false);return this.locker.lock(otherPath,this.tid,forWriting,`moved to "/${otherPath}" (queued): ${this.comment}`,{withPriority:true}).then(newLock=>{return newLock})}}}module.exports={NodeLocker:NodeLocker,NodeLock:NodeLock}},{"acebase-core":11}],36:[function(require,module,exports){const VALUE_TYPES={OBJECT:1,ARRAY:2,NUMBER:3,BOOLEAN:4,STRING:5,DATETIME:6,BINARY:8,REFERENCE:9};function getValueTypeName(valueType){switch(valueType){case VALUE_TYPES.ARRAY:return"array";case VALUE_TYPES.BINARY:return"binary";case VALUE_TYPES.BOOLEAN:return"boolean";case VALUE_TYPES.DATETIME:return"date";case VALUE_TYPES.NUMBER:return"number";case VALUE_TYPES.OBJECT:return"object";case VALUE_TYPES.REFERENCE:return"reference";case VALUE_TYPES.STRING:return"string";default:"unknown"}}module.exports={VALUE_TYPES:VALUE_TYPES,getValueTypeName:getValueTypeName}},{}],37:[function(require,module,exports){const{Storage:Storage}=require("./storage");const{NodeInfo:NodeInfo}=require("./node-info");const{VALUE_TYPES:VALUE_TYPES,getValueTypeName:getValueTypeName}=require("./node-value-types");const colors=require("colors");class Node{static get VALUE_TYPES(){return VALUE_TYPES}static getInfo(storage,path,options={no_cache:false}){if(options&&!options.no_cache){let cachedInfo=storage.nodeCache.find(path);if(cachedInfo){return Promise.resolve(cachedInfo)}}return storage.getNodeInfo(path).then(info=>{if(options&&!options.no_cache){storage.nodeCache.update(info)}return info})}static update(storage,path,value,options={merge:true}){if(options.merge){return storage.updateNode(path,value)}else{return storage.setNode(path,value)}}static exists(storage,path){return storage.getNodeInfo(path).then(nodeInfo=>{return nodeInfo.exists})}static getValue(storage,path,options={include:undefined,exclude:undefined,child_objects:true}){if(!options){options={}}if(typeof options.include!=="undefined"&&!(options.include instanceof Array)){throw new TypeError(`options.include must be an array of key names`)}if(typeof options.exclude!=="undefined"&&!(options.exclude instanceof Array)){throw new TypeError(`options.exclude must be an array of key names`)}if(["undefined","boolean"].indexOf(typeof options.child_objects)<0){throw new TypeError(`options.child_objects must be a boolean`)}return storage.getNodeValue(path,options)}static getChildInfo(storage,path,childKeyOrIndex){let childInfo;return storage.getChildren(path,{keyFilter:[childKeyOrIndex]}).next(info=>{childInfo=info}).then(()=>{return childInfo})}static getChildren(storage,path,keyFilter=undefined){return storage.getChildren(path,{keyFilter:keyFilter})}static remove(storage,path){return storage.removeNode(path)}static set(storage,path,value){return Node.update(storage,path,value,{merge:false})}static transaction(storage,path,callback){return storage.transactNode(path,callback)}static matches(storage,path,criteria,options){return storage.matchNode(path,criteria,options)}}class NodeChange{static get CHANGE_TYPE(){return{UPDATE:"update",DELETE:"delete",INSERT:"insert"}}constructor(keyOrIndex,changeType,oldValue,newValue){this.keyOrIndex=keyOrIndex;this.changeType=changeType;this.oldValue=oldValue;this.newValue=newValue}}class NodeChangeTracker{constructor(path){this.path=path;this._changes=[];this._oldValue=undefined;this._newValue=undefined}addDelete(keyOrIndex,oldValue){this._changes.push(new NodeChange(keyOrIndex,NodeChange.CHANGE_TYPE.DELETE,oldValue,null))}addUpdate(keyOrIndex,oldValue,newValue){this._changes.push(new NodeChange(keyOrIndex,NodeChange.CHANGE_TYPE.UPDATE,oldValue,newValue))}addInsert(keyOrIndex,newValue){this._changes.push(new NodeChange(keyOrIndex,NodeChange.CHANGE_TYPE.INSERT,null,newValue))}add(keyOrIndex,currentValue,newValue){if(currentValue===null){if(newValue===null){throw new Error(`Wrong logic for node change on "${this.nodeInfo.path}/${keyOrIndex}" - both old and new values are null`)}this.addInsert(keyOrIndex,newValue)}else if(newValue===null){this.addDelete(keyOrIndex,currentValue)}else{this.addUpdate(keyOrIndex,currentValue,newValue)}}get updates(){return this._changes.filter(change=>change.changeType===NodeChange.CHANGE_TYPE.UPDATE)}get deletes(){return this._changes.filter(change=>change.changeType===NodeChange.CHANGE_TYPE.DELETE)}get inserts(){return this._changes.filter(change=>change.changeType===NodeChange.CHANGE_TYPE.INSERT)}get all(){return this._changes}get totalChanges(){return this._changes.length}get(keyOrIndex){return this._changes.find(change=>change.keyOrIndex===keyOrIndex)}hasChanged(keyOrIndex){return!!this.get(keyOrIndex)}get newValue(){if(typeof this._newValue==="object"){return this._newValue}if(typeof this._oldValue==="undefined"){throw new TypeError(`oldValue is not set`)}let newValue={};Object.keys(this.oldValue).forEach(key=>newValue[key]=oldValue[key]);this.deletes.forEach(change=>delete newValue[change.key]);this.updates.forEach(change=>newValue[change.key]=change.newValue);this.inserts.forEach(change=>newValue[change.key]=change.newValue);return newValue}set newValue(value){this._newValue=value}get oldValue(){if(typeof this._oldValue==="object"){return this._oldValue}if(typeof this._newValue==="undefined"){throw new TypeError(`newValue is not set`)}let oldValue={};Object.keys(this.newValue).forEach(key=>oldValue[key]=newValue[key]);this.deletes.forEach(change=>oldValue[change.key]=change.oldValue);this.updates.forEach(change=>oldValue[change.key]=change.oldValue);this.inserts.forEach(change=>delete oldValue[change.key]);return oldValue}set oldValue(value){this._oldValue=value}get typeChanged(){return typeof this.oldValue!==typeof this.newValue||this.oldValue instanceof Array&&!(this.newValue instanceof Array)||this.newValue instanceof Array&&!(this.oldValue instanceof Array)}static create(path,oldValue,newValue){const changes=new NodeChangeTracker(path);changes.oldValue=oldValue;changes.newValue=newValue;typeof oldValue==="object"&&Object.keys(oldValue).forEach(key=>{if(typeof newValue==="object"&&key in newValue&&newValue!==null){changes.add(key,oldValue[key],newValue[key])}else{changes.add(key,oldValue[key],null)}});typeof newValue==="object"&&Object.keys(newValue).forEach(key=>{if(typeof oldValue!=="object"||!(key in oldValue)||oldValue[key]===null){changes.add(key,null,newValue[key])}});return changes}}module.exports={Node:Node,NodeInfo:NodeInfo}},{"./node-info":34,"./node-value-types":36,"./storage":39,colors:22}],38:[function(require,module,exports){const{debug:debug,ID:ID,PathReference:PathReference,PathInfo:PathInfo,ascii85:ascii85}=require("acebase-core");const{NodeInfo:NodeInfo}=require("./node-info");const{NodeLocker:NodeLocker}=require("./node-lock");const{VALUE_TYPES:VALUE_TYPES}=require("./node-value-types");const{Storage:Storage,StorageSettings:StorageSettings,NodeNotFoundError:NodeNotFoundError}=require("./storage");class ICustomStorageNodeMetaData{constructor(){this.revision="";this.revision_nr=0;this.created=0;this.modified=0;this.type=0}}class ICustomStorageNode extends ICustomStorageNodeMetaData{constructor(){super();this.value=null}}class CustomStorageTransaction{constructor(target){this.target={get originalPath(){return target.path},path:target.path,get write(){return target.write}};this.id=ID.generate()}get(path){throw new Error(`CustomStorageTransaction.get must be overridden by subclass`)}set(path,node){throw new Error(`CustomStorageTransaction.set must be overridden by subclass`)}remove(path){throw new Error(`CustomStorageTransaction.remove must be overridden by subclass`)}childrenOf(path,include,checkCallback,addCallback){throw new Error(`CustomStorageTransaction.childrenOf must be overridden by subclass`)}descendantsOf(path,include,checkCallback,addCallback){throw new Error(`CustomStorageTransaction.descendantsOf must be overridden by subclass`)}getMultiple(paths){const map=new Map;return Promise.all(paths.map(path=>this.get(path).then(val=>map.set(path,val)))).then(done=>map)}async setMultiple(nodes){await Promise.all(paths.map(({path:path,node:node})=>this.set(path,node)))}async removeMultiple(paths){await Promise.all(paths.map(path=>this.remove(path)))}rollback(reason){throw new Error(`CustomStorageTransaction.rollback must be overridden by subclass`)}commit(){throw new Error(`CustomStorageTransaction.rollback must be overridden by subclass`)}async moveToParentPath(targetPath){const currentPath=this._lock&&this._lock.path||this.target.path;if(currentPath===targetPath){return targetPath}const pathInfo=CustomStorageHelpers.PathInfo.get(targetPath);if(pathInfo.isParentOf(currentPath)){if(this._lock){this._lock=await this._lock.moveToParent()}}else{throw new Error(`Locking issue. Locked path "${this._lock.path}" is not a child/descendant of "${targetPath}"`)}this.target.path=targetPath;return targetPath}}class CustomStorageSettings extends StorageSettings{constructor(settings){super(settings);settings=settings||{};if(typeof settings.ready!=="function"){throw new Error(`ready must be a function`)}if(typeof settings.getTransaction!=="function"){throw new Error(`getTransaction must be a function`)}this.name=settings.name;this.info=`${this.name||"CustomStorage"} realtime database`;this.locking=settings.locking!==false;this.ready=settings.ready;const useLocking=this.locking;const nodeLocker=useLocking?new NodeLocker:null;this.getTransaction=async({path:path,write:write})=>{const transaction=await settings.getTransaction({path:path,write:write});console.assert(typeof transaction.id==="string",`transaction id not set`);const rollback=transaction.rollback;const commit=transaction.commit;transaction.commit=async()=>{const ret=await commit.call(transaction);if(useLocking){await transaction._lock.release("commit")}return ret};transaction.rollback=async reason=>{const ret=await rollback.call(transaction,reason);if(useLocking){await transaction._lock.release("rollback")}return ret};if(useLocking){transaction._lock=await nodeLocker.lock(path,transaction.id,write,`${this.name}::getTransaction`)}return transaction}}}class CustomStorageNodeAddress{constructor(containerPath){this.path=containerPath}}class CustomStorageNodeInfo extends NodeInfo{constructor(info){super(info);this.address;this.revision=info.revision;this.revision_nr=info.revision_nr;this.created=info.created;this.modified=info.modified}}class CustomStorageHelpers{static ChildPathsSql(path,columnName="path"){const where=path===""?`${columnName} <> '' AND ${columnName} NOT LIKE '%/%'`:`(${columnName} LIKE '${path}/%' OR ${columnName} LIKE '${path}[%') AND ${columnName} NOT LIKE '${path}/%/%' AND ${columnName} NOT LIKE '${path}[%]/%' AND ${columnName} NOT LIKE '${path}[%][%'`;return where}static ChildPathsRegex(path){return new RegExp(`^${path}(?:/[^/[]+|[[0-9]+])$`)}static DescendantPathsSql(path,columnName="path"){const where=path===""?`${columnName} <> ''`:`${columnName} LIKE '${path}/%' OR ${columnName} LIKE '${path}[%'`;return where}static DescendantPathsRegex(path){return new RegExp(`^${path}(?:/[^/[]+|[[0-9]+])`)}static get PathInfo(){return PathInfo}}class CustomStorage extends Storage{constructor(dbname,settings){super(dbname,settings);this._init()}async _init(){this._customImplementation=this.settings;this.debug.log(`Database "${this.name}" details:`.intro);this.debug.log(`- Type: CustomStorage`);this.debug.log(`- Path: ${this.settings.path}`);this.debug.log(`- Max inline value size: ${this.settings.maxInlineValueSize}`.intro);this.debug.log(`- Autoremove undefined props: ${this.settings.removeVoidProperties}`);await this._customImplementation.ready();const transaction=await this._customImplementation.getTransaction({path:"",write:true});const info=await this.getNodeInfo("",{transaction:transaction});if(!info.exists){await this._writeNode("",{},{transaction:transaction})}await transaction.commit();if(this.indexes.supported){await this.indexes.load()}this.emit("ready")}_storeNode(path,node,options){const getTypedChildValue=val=>{if(val===null){throw new Error(`Not allowed to store null values. remove the property`)}else if(["string","number","boolean"].includes(typeof val)){return val}else if(val instanceof Date){return{type:VALUE_TYPES.DATETIME,value:val.getTime()}}else if(val instanceof PathReference){return{type:VALUE_TYPES.REFERENCE,value:child.path}}else if(val instanceof ArrayBuffer){return{type:VALUE_TYPES.BINARY,value:ascii85.encode(val)}}else if(typeof val==="object"){console.assert(Object.keys(val).length===0,"child object stored in parent can only be empty");return val}};const unprocessed=`Caller should have pre-processed the value by converting it to a string`;if(node.type===VALUE_TYPES.ARRAY&&node.value instanceof Array){console.warn(`Unprocessed array. ${unprocessed}`);const obj={};for(let i=0;i{node.value[key]=getTypedChildValue(original[key])})}return options.transaction.set(path,node)}_processReadNodeValue(node){const getTypedChildValue=val=>{if(val.type===VALUE_TYPES.BINARY){return ascii85.decode(val.value)}else if(val.type===VALUE_TYPES.DATETIME){return new Date(val.value)}else if(val.type===VALUE_TYPES.REFERENCE){return new PathReference(val.value)}else{throw new Error(`Unhandled child value type ${val.type}`)}};switch(node.type){case VALUE_TYPES.ARRAY:case VALUE_TYPES.OBJECT:{const obj=node.value;Object.keys(obj).forEach(key=>{let item=obj[key];if(typeof item==="object"&&"type"in item){obj[key]=getTypedChildValue(item)}});node.value=obj;break}case VALUE_TYPES.BINARY:{node.value=ascii85.decode(node.value);break}case VALUE_TYPES.REFERENCE:{node.value=new PathReference(node.value);break}case VALUE_TYPES.STRING:{break}default:throw new Error(`Invalid standalone record value type`)}}async _readNode(path,options){let node=await options.transaction.get(path);if(node===null){return null}if(typeof node!=="object"){throw new Error(`CustomStorage get function must return an ICustomStorageNode object. Use JSON.parse if your set function stored it as a string`)}this._processReadNodeValue(node);return node}_getTypeFromStoredValue(val){let type;if(typeof val==="string"){type=VALUE_TYPES.STRING}else if(typeof val==="number"){type=VALUE_TYPES.NUMBER}else if(typeof val==="boolean"){type=VALUE_TYPES.BOOLEAN}else if(val instanceof Array){type=VALUE_TYPES.ARRAY}else if(typeof val==="object"){if("type"in val){type=val.type;val=val.value;if(type===VALUE_TYPES.DATETIME){val=new Date(val)}else if(type===VALUE_TYPES.REFERENCE){val=new PathReference(val)}}else{type=VALUE_TYPES.OBJECT}}else{throw new Error(`Unknown value type`)}return{type:type,value:val}}async _writeNode(path,value,options){if(this.valueFitsInline(value)&&path!==""){throw new Error(`invalid value to store in its own node`)}else if(path===""&&(typeof value!=="object"||value instanceof Array)){throw new Error(`Invalid root node value. Must be an object`)}const transaction=options.transaction;const currentRow=await this._readNode(path,{transaction:transaction});if(options.merge&¤tRow){if(currentRow.type===VALUE_TYPES.ARRAY&&!(value instanceof Array)&&typeof value==="object"&&Object.keys(value).some(key=>isNaN(key))){throw new Error(`Cannot merge existing array of path "${path}" with an object`)}if(value instanceof Array&¤tRow.type!==VALUE_TYPES.ARRAY){throw new Error(`Cannot merge existing object of path "${path}" with an array`)}}const revision=options.revision||ID.generate();let mainNode={type:currentRow&¤tRow.type===VALUE_TYPES.ARRAY?VALUE_TYPES.ARRAY:VALUE_TYPES.OBJECT,value:{}};const childNodeValues={};if(value instanceof Array){mainNode.type=VALUE_TYPES.ARRAY;const obj={};for(let i=0;i{const val=value[key];delete mainNode.value[key];if(val===null){return}else if(typeof val==="undefined"){if(this.settings.removeVoidProperties===true){delete value[key];return}else{throw new Error(`Property "${key}" has invalid value. Cannot store undefined values. Set removeVoidProperties option to true to automatically remove undefined properties`)}}if(this.valueFitsInline(val)){mainNode.value[key]=val}else{childNodeValues[key]=val}})}const isArray=mainNode.type===VALUE_TYPES.ARRAY;if(currentRow){this.debug.log(`Node "/${path}" is being ${options.merge?"updated":"overwritten"}`.cyan);if(currentIsObjectOrArray||newIsObjectOrArray){const pathInfo=PathInfo.get(path);const keys=[];let checkExecuted=false;const includeChildCheck=childPath=>{checkExecuted=true;if(!pathInfo.isParentOf(childPath)){throw new Error(`"${childPath}" is not a child of "${path}" - childrenOf must only check and return paths that are children`)}return true};const addChildPath=childPath=>{if(!checkExecuted){throw new Error(`${this._customImplementation.info} childrenOf did not call checkCallback before addCallback`)}const key=PathInfo.get(childPath).key;keys.push(key.toString());return true};await transaction.childrenOf(path,{metadata:false,value:false},includeChildCheck,addChildPath);children.current=children.current.concat(keys);if(newIsObjectOrArray){if(options&&options.merge){children.new=children.current.slice()}Object.keys(value).forEach(key=>{if(!children.new.includes(key)){children.new.push(key)}})}const changes={insert:children.new.filter(key=>!children.current.includes(key)),update:[],delete:options&&options.merge?Object.keys(value).filter(key=>value[key]===null):children.current.filter(key=>!children.new.includes(key))};changes.update=children.new.filter(key=>children.current.includes(key)&&!changes.delete.includes(key));if(isArray&&options.merge&&(changes.insert.length>0||changes.delete.length>0)){const newArrayKeys=changes.update.concat(changes.insert);const isExhaustive=newArrayKeys.every((k,index,arr)=>arr.includes(index.toString()));if(!isExhaustive){throw new Error(`Elements cannot be inserted beyond, or removed before the end of an array. Rewrite the whole array at path "${path}" or change your schema to use an object collection instead`)}}const writePromises=Object.keys(childNodeValues).map(key=>{if(isArray){key=parseInt(key)}const childPath=pathInfo.childPath(key);const childValue=childNodeValues[key];return this._writeNode(childPath,childValue,{transaction:transaction,revision:revision,merge:false})});const movingNodes=keys.filter(key=>key in mainNode.value);const deleteDedicatedKeys=changes.delete.concat(movingNodes);const deletePromises=deleteDedicatedKeys.map(key=>{if(isArray){key=parseInt(key)}const childPath=pathInfo.childPath(key);return this._deleteNode(childPath,{transaction:transaction})});const promises=writePromises.concat(deletePromises);await Promise.all(promises)}return await this._storeNode(path,{type:mainNode.type,value:mainNode.value,revision:currentRow.revision,revision_nr:currentRow.revision_nr+1,created:currentRow.created,modified:Date.now()},{transaction:transaction})}else{this.debug.log(`Node "/${path}" is being created`.cyan);if(isArray){const arrayKeys=Object.keys(mainNode.value).concat(Object.keys(childNodeValues));const isExhaustive=arrayKeys.every((k,index,arr)=>arr.includes(index.toString()));if(!isExhaustive){throw new Error(`Cannot store arrays with missing entries`)}}const promises=Object.keys(childNodeValues).map(key=>{if(isArray){key=parseInt(key)}const childPath=PathInfo.getChildPath(path,key);const childValue=childNodeValues[key];return this._writeNode(childPath,childValue,{transaction:transaction,revision:revision,merge:false})});const p=this._storeNode(path,{type:mainNode.type,value:mainNode.value,revision:revision,revision_nr:1,created:Date.now(),modified:Date.now()},{transaction:transaction});promises.push(p);return Promise.all(promises)}}async _deleteNode(path,options){const pathInfo=PathInfo.get(path);this.debug.log(`Node "/${path}" is being deleted`.cyan);const deletePaths=[path];let checkExecuted=false;const includeDescendantCheck=descPath=>{checkExecuted=true;if(!pathInfo.isAncestorOf(descPath)){throw new Error(`"${descPath}" is not a descendant of "${path}" - descendantsOf must only check and return paths that are descendants`)}return true};const addDescendant=descPath=>{if(!checkExecuted){throw new Error(`${this._customImplementation.info} descendantsOf did not call checkCallback before addCallback`)}deletePaths.push(descPath);return true};const transaction=options.transaction;await transaction.descendantsOf(path,{metadata:false,value:false},includeDescendantCheck,addDescendant);this.debug.log(`Nodes ${deletePaths.map(p=>`"/${p}"`).join(",")} are being deleted`.cyan);return transaction.removeMultiple(deletePaths)}getChildren(path,options){options=options||{};var callback;const generator={next(valueCallback){callback=valueCallback;return start()}};const start=async()=>{const transaction=options.transaction||await this._customImplementation.getTransaction({path:path,write:false});try{let canceled=false;await(async()=>{let node=await this._readNode(path,{transaction:transaction});if(!node){throw new NodeNotFoundError(`Node "/${path}" does not exist`)}if(![VALUE_TYPES.OBJECT,VALUE_TYPES.ARRAY].includes(node.type)){return}const isArray=node.type===VALUE_TYPES.ARRAY;const value=node.value;let keys=Object.keys(value);if(options.keyFilter){keys=keys.filter(key=>options.keyFilter.includes(key))}const pathInfo=PathInfo.get(path);keys.length>0&&keys.every(key=>{let child=this._getTypeFromStoredValue(value[key]);const info=new CustomStorageNodeInfo({path:pathInfo.childPath(key),key:isArray?null:key,index:isArray?key:null,type:child.type,address:null,exists:true,value:child.value,revision:node.revision,revision_nr:node.revision_nr,created:node.created,modified:node.modified});canceled=callback(info)===false;return!canceled});if(canceled){return}let checkExecuted=false;const includeChildCheck=childPath=>{checkExecuted=true;if(!pathInfo.isParentOf(childPath)){throw new Error(`"${childPath}" is not a child of "${path}" - childrenOf must only check and return paths that are children`)}if(options.keyFilter){const key=PathInfo.get(childPath).key;return options.keyFilter.includes(key)}return true};const addChildNode=(childPath,node)=>{if(!checkExecuted){throw new Error(`${this._customImplementation.info} childrenOf did not call checkCallback before addCallback`)}const key=PathInfo.get(childPath).key;const info=new CustomStorageNodeInfo({path:childPath,type:node.type,key:isArray?null:key,index:isArray?key:null,address:new CustomStorageNodeAddress(childPath),exists:true,value:null,revision:node.revision,revision_nr:node.revision_nr,created:new Date(node.created),modified:new Date(node.modified)});canceled=callback(info)===false;return!canceled};await transaction.childrenOf(path,{metadata:true,value:false},includeChildCheck,addChildNode)})();if(!options.transaction){await transaction.commit()}return canceled}catch(err){if(!options.transaction){await transaction.rollback(err)}throw err}};return generator}async getNode(path,options){options=options||{};const transaction=options.transaction||await this._customImplementation.getTransaction({path:path,write:false});try{const node=await(async()=>{const filtered=options.include||options.exclude||options.child_objects===false;const pathInfo=PathInfo.get(path);const targetNode=await this._readNode(path,{transaction:transaction});if(!targetNode){if(path===""){return{value:null}}const lockPath=await transaction.moveToParentPath(pathInfo.parentPath);console.assert(lockPath===pathInfo.parentPath,`transaction.moveToParentPath() did not move to the right parent path of "${path}"`);let parentNode=await this._readNode(pathInfo.parentPath,{transaction:transaction});if(parentNode&&[VALUE_TYPES.OBJECT,VALUE_TYPES.ARRAY].includes(parentNode.type)&&pathInfo.key in parentNode){const childValueInfo=this._getTypeFromStoredValue(parentNode.value[pathInfo.key]);return{revision:parentNode.revision,revision_nr:parentNode.revision_nr,created:parentNode.created,modified:parentNode.modified,type:childValueInfo.type,value:childValueInfo.value}}return{value:null}}const includeCheck=options.include?new RegExp("^"+options.include.map(p=>"(?:"+p.replace(/\*/g,"[^/\\[]+")+")").join("|")+"(?:$|[/\\[])"):null;const excludeCheck=options.exclude?new RegExp("^"+options.exclude.map(p=>"(?:"+p.replace(/\*/g,"[^/\\[]+")+")").join("|")+"(?:$|[/\\[])"):null;let checkExecuted=false;const includeDescendantCheck=descPath=>{checkExecuted=true;if(!pathInfo.isAncestorOf(descPath)){throw new Error(`"${descPath}" is not a descendant of "${path}" - descendantsOf must only check and return paths that are descendants`)}if(!filtered){return true}let checkPath=descPath.slice(path.length);if(checkPath[0]==="/"){checkPath=checkPath.slice(1)}let include=(includeCheck?includeCheck.test(checkPath):true)&&(excludeCheck?!excludeCheck.test(checkPath):true);if(include&&options.child_objects===false&&(pathInfo.isParentOf(descPath)&&[VALUE_TYPES.OBJECT,VALUE_TYPES.ARRAY].includes(childNode.type)||PathInfo.getPathKeys(descPath).length>pathInfo.pathKeys.length+1)){include=false}return include};const descRows=[];const addDescendant=(descPath,node)=>{if(!checkExecuted){throw new Error(`${this._customImplementation.info} descendantsOf did not call checkCallback before addCallback`)}this._processReadNodeValue(node);node.path=descPath;descRows.push(node);return true};await transaction.descendantsOf(path,{metadata:true,value:true},includeDescendantCheck,addDescendant);this.debug.log(`Read node "/${path}" and ${filtered?"(filtered) ":""}descendants from ${descRows.length+1} records`.magenta);const result=targetNode;const objectToArray=obj=>{const arr=[];Object.keys(obj).forEach(key=>{let index=parseInt(key);arr[index]=obj[index]});return arr};if(targetNode.type===VALUE_TYPES.ARRAY){result.value=objectToArray(result.value)}if(targetNode.type===VALUE_TYPES.OBJECT||targetNode.type===VALUE_TYPES.ARRAY){const targetPathKeys=PathInfo.getPathKeys(path);let value=targetNode.value;for(let i=0;i{console.assert(!(childKey in parent[key]),"child key is in parent value already?! HOW?!");parent[key][childKey]=nodeValue[childKey]})}else{parent[key]=nodeValue}parent=parent[key]}}}else if(descRows.length>0){throw new Error(`multiple records found for non-object value!`)}if(options.child_objects===false){Object.keys(result.value).forEach(key=>{if(typeof result.value[key]==="object"&&result.value[key].constructor===Object){console.assert(Object.keys(result.value[key]).length===0);delete result.value[key]}})}if(options.exclude){const process=(obj,keys)=>{if(typeof obj!=="object"){return}const key=keys[0];if(key==="*"){Object.keys(obj).forEach(k=>{process(obj[k],keys.slice(1))})}else if(keys.length>1){key in obj&&process(obj[key],keys.slice(1))}else{delete obj[key]}};options.exclude.forEach(path=>{const checkKeys=PathInfo.getPathKeys(path);process(result.value,checkKeys)})}return result})();if(!options.transaction){await transaction.commit()}return node}catch(err){if(!options.transaction){await transaction.rollback(err)}throw err}}async getNodeInfo(path,options){options=options||{};const pathInfo=PathInfo.get(path);const transaction=options.transaction||await this._customImplementation.getTransaction({path:path,write:true});try{const node=await this._readNode(path,{transaction:transaction});const info=new CustomStorageNodeInfo({path:path,key:typeof pathInfo.key==="string"?pathInfo.key:null,index:typeof pathInfo.key==="number"?pathInfo.key:null,type:node?node.type:0,exists:node!==null,address:node?new CustomStorageNodeAddress(path):null,created:node?new Date(node.created):null,modified:node?new Date(node.modified):null,revision:node?node.revision:null,revision_nr:node?node.revision_nr:null});if(!node&&path!==""){const lockPath=await transaction.moveToParentPath(pathInfo.parentPath);console.assert(lockPath===pathInfo.parentPath,`transaction.moveToParentPath() did not move to the right parent path of "${path}"`);const parent=await this._readNode(pathInfo.parentPath,{transaction:transaction});if(parent&&[VALUE_TYPES.OBJECT,VALUE_TYPES.ARRAY].includes(parent.type)&&pathInfo.key in parent.value){info.exists=true;info.value=parent.value[pathInfo.key];info.address=null;info.type=parent.type;info.created=new Date(parent.created);info.modified=new Date(parent.modified);info.revision=parent.revision;info.revision_nr=parent.revision_nr}else{info.address=null}}if(!options.transaction){await transaction.commit()}return info}catch(err){if(!options.transaction){await transaction.rollback(err)}throw err}}async removeNode(path,options){if(path===""){return Promise.reject(new Error(`Cannot remove the root node`))}options=options||{};const pathInfo=PathInfo.get(path);const transaction=options.transaction||this._customImplementation.getTransaction({path:path,write:true});try{await this.updateNode(pathInfo.parentPath,{[pathInfo.key]:null},{transaction:transaction});if(!options.transaction){await transaction.commit()}}catch(err){if(!options.transaction){await transaction.rollback(err)}throw err}}async setNode(path,value,options){const pathInfo=PathInfo.get(path);options=options||{};const transaction=options.transaction||await this._customImplementation.getTransaction({path:path,write:true});try{if(path===""){if(value===null||typeof value!=="object"||value instanceof Array||value instanceof ArrayBuffer||"buffer"in value&&value.buffer instanceof ArrayBuffer){throw new Error(`Invalid value for root node: ${value}`)}await this._writeNodeWithTracking("",value,{merge:false,transaction:transaction})}else if(typeof options.assert_revision!=="undefined"){const info=await this.getNodeInfo(path,{transaction:transaction});if(info.revision!==options.assert_revision){throw new NodeRevisionError(`revision '${info.revision}' does not match requested revision '${options.assert_revision}'`)}if(info.address&&info.address.path===path&&!this.valueFitsInline(value)){await this._writeNodeWithTracking(path,value,{merge:false,transaction:transaction})}else{const lockPath=await transaction.moveToParentPath(pathInfo.parentPath);console.assert(lockPath===pathInfo.parentPath,`transaction.moveToParentPath() did not move to the right parent path of "${path}"`);await this._writeNodeWithTracking(pathInfo.parentPath,{[pathInfo.key]:value},{merge:true,transaction:transaction})}}else{const lockPath=await transaction.moveToParentPath(pathInfo.parentPath);console.assert(lockPath===pathInfo.parentPath,`transaction.moveToParentPath() did not move to the right parent path of "${path}"`);await this.updateNode(pathInfo.parentPath,{[pathInfo.key]:value},{transaction:transaction})}if(!options.transaction){await transaction.commit()}}catch(err){if(!options.transaction){await transaction.rollback(err)}throw err}}async updateNode(path,updates,options){if(typeof updates!=="object"){throw new Error(`invalid updates argument`)}options=options||{};const transaction=options.transaction||await this._customImplementation.getTransaction({path:path,write:true});try{const nodeInfo=await this.getNodeInfo(path,{transaction:transaction});const pathInfo=PathInfo.get(path);if(nodeInfo.exists&&nodeInfo.address&&nodeInfo.address.path===path){await this._writeNodeWithTracking(path,updates,{transaction:transaction,merge:true})}else if(nodeInfo.exists){const pathInfo=PathInfo.get(path);const lockPath=await transaction.moveToParentPath(pathInfo.parentPath);console.assert(lockPath===pathInfo.parentPath,`transaction.moveToParentPath() did not move to the right parent path of "${path}"`);await this._writeNodeWithTracking(pathInfo.parentPath,{[pathInfo.key]:updates},{transaction:transaction,merge:true})}else{const lockPath=await transaction.moveToParentPath(pathInfo.parentPath);console.assert(lockPath===pathInfo.parentPath,`transaction.moveToParentPath() did not move to the right parent path of "${path}"`);await this.updateNode(pathInfo.parentPath,{[pathInfo.key]:updates},{transaction:transaction})}if(!options.transaction){await transaction.commit()}}catch(err){if(!options.transaction){await transaction.rollback(err)}throw err}}}module.exports={CustomStorageNodeAddress:CustomStorageNodeAddress,CustomStorageNodeInfo:CustomStorageNodeInfo,CustomStorage:CustomStorage,CustomStorageSettings:CustomStorageSettings,CustomStorageHelpers:CustomStorageHelpers,CustomStorageTransaction:CustomStorageTransaction,ICustomStorageNodeMetaData:ICustomStorageNodeMetaData,ICustomStorageNode:ICustomStorageNode}},{"./node-info":34,"./node-lock":35,"./node-value-types":36,"./storage":39,"acebase-core":11}],39:[function(require,module,exports){(function(process){const{Utils:Utils,DebugLogger:DebugLogger,PathInfo:PathInfo,ID:ID,PathReference:PathReference,ascii85:ascii85}=require("acebase-core");const{NodeLocker:NodeLocker}=require("./node-lock");const{VALUE_TYPES:VALUE_TYPES,getValueTypeName:getValueTypeName}=require("./node-value-types");const{NodeInfo:NodeInfo}=require("./node-info");const{EventEmitter:EventEmitter}=require("events");const{cloneObject:cloneObject,compareValues:compareValues,getChildValues:getChildValues,encodeString:encodeString}=Utils;const colors=require("colors");class NodeNotFoundError extends Error{}class NodeRevisionError extends Error{}class ClusterSettings{constructor(settings){settings=settings||{};this.enabled=settings.enabled===true;this.isMaster=settings.isMaster===true;this.master=this.isMaster?null:settings.master;this.workers=this.isMaster?settings.workers:null}}class ClusterManager extends EventEmitter{constructor(settings){super();this.settings=new ClusterSettings(settings);if(!settings.enabled){}else if(settings.isMaster){settings.workers.forEach(worker=>{worker.on("message",data=>{const{id:id,request:request}=data;if(typeof request==="object"&&request.type==="ping"){worker.send({id:id,result:"pong"})}else{const reply=result=>{worker.send({id:id,result:result})};const broadcast=msg=>{console.assert(!("id"in msg),"message to broadcast cannot have id property, it will confuse workers because they think it is a reply to their request");settings.workers.forEach(otherWorker=>{if(otherWorker!==worker){otherWorker.send(msg)}})};this.emit("worker_request",{request:request,reply:reply,broadcast:broadcast})}})});this.request=msg=>{throw new Error(`request can only be called by worker processes!`)}}else{const master=settings.master;const requests={};this.request=msg=>{return new Promise((resolve,reject)=>{const id=ID.generate();requests[id]=resolve;master.send({id:id,request:msg})})};master.on("message",data=>{if(typeof data.id!=="undefined"){let resolve=requests[data.id];delete requests[data.id];resolve(data.result)}else{this.emit("master_notification",data)}});this.request({type:"ping"}).then(result=>{console.log(`PING master process result: ${result}`)})}}get isMaster(){return this.settings.isMaster}get enabled(){return this.settings.enabled}}class StorageSettings{constructor(settings){settings=settings||{};this.maxInlineValueSize=typeof settings.maxInlineValueSize==="number"?settings.maxInlineValueSize:50;this.removeVoidProperties=settings.removeVoidProperties===true;this.cluster=new ClusterSettings(settings.cluster);this.path=settings.path||".";if(this.path.endsWith("/")){this.path=this.path.slice(0,-1)}this.logLevel=settings.logLevel||"log";this.info=settings.info||"realtime database"}}class Storage extends EventEmitter{constructor(name,settings){super();this.name=name;this.settings=settings;this.debug=new DebugLogger(settings.logLevel,`[${name}]`);colors.setTheme({art:["magenta","bold"],intro:["dim"]});const logo=" ___ ______ ".art+"\n"+" / _ \\ | ___ \\ ".art+"\n"+" / /_\\ \\ ___ ___| |_/ / __ _ ___ ___ ".art+"\n"+" | _ |/ __/ _ \\ ___ \\/ _` / __|/ _ \\".art+"\n"+" | | | | (_| __/ |_/ / (_| \\__ \\ __/".art+"\n"+" \\_| |_/\\___\\___\\____/ \\__,_|___/\\___|".art+"\n"+(settings.info?"".padStart(40-settings.info.length," ")+settings.info.magenta+"\n":"");this.debug.write(logo);this.nodeCache={find(path){return null},update(path,info){}};this.nodeLocker=new NodeLocker;this.cluster=new ClusterManager(settings.cluster);const{DataIndex:DataIndex,ArrayIndex:ArrayIndex,FullTextIndex:FullTextIndex,GeoIndex:GeoIndex}=require("./data-index");const _indexes=[];const storage=this;this.indexes={get supported(){const pfs=require("./promise-fs");return pfs&&pfs.hasFileSystem},create(path,key,options={rebuild:false,type:undefined,include:undefined}){path=path.replace(/\/\*$/,"");const rebuild=options&&options.rebuild===true;const indexType=options&&options.type||"normal";let includeKeys=options&&options.include||[];if(typeof includeKeys==="string"){includeKeys=[includeKeys]}const existingIndex=_indexes.find(index=>index.path===path&&index.key===key&&index.type===indexType&&index.includeKeys.length===includeKeys.length&&index.includeKeys.every((key,index)=>includeKeys[index]===key));if(existingIndex&&rebuild!==true){storage.debug.log(`Index on "/${path}/*/${key}" already exists`.inverse);return Promise.resolve(existingIndex)}const index=existingIndex||(()=>{switch(indexType){case"array":return new ArrayIndex(storage,path,key,{include:options.include,config:options.config});case"fulltext":return new FullTextIndex(storage,path,key,{include:options.include,config:options.config});case"geo":return new GeoIndex(storage,path,key,{include:options.include,config:options.config});default:return new DataIndex(storage,path,key,{include:options.include,config:options.config})}})();if(!existingIndex){_indexes.push(index)}return index.build().then(()=>{return index}).catch(err=>{storage.debug.error(`Index build on "/${path}/*/${key}" failed: ${err.message} (code: ${err.code})`.red);if(!existingIndex){_indexes.splice(_indexes.indexOf(index),1)}throw err})},get(path,key=null){const matchesNamedWildcardPath=index=>{if(!index.path.includes("$")){return false}const pattern="^"+index.path.replace(/\$[a-z0-9_]+/gi,"[a-z0-9_]+|\\*")+"$";const re=new RegExp(pattern,"i");return re.test(path)};return _indexes.filter(index=>(index.path===path||matchesNamedWildcardPath(index))&&(key===null||key===index.key))},getAll(targetPath,options={parentPaths:true,childPaths:true}){const pathKeys=PathInfo.getPathKeys(targetPath);return _indexes.filter(index=>{const indexKeys=PathInfo.getPathKeys(index.path+"/*");if(options.parentPaths&&indexKeys.every((key,i)=>{return key==="*"||pathKeys[i]===key})&&[index.key].concat(...index.includeKeys).includes(pathKeys[indexKeys.length])){return true}else if(indexKeys.length{return[key,"*"].includes(indexKeys[i])})})},list(){return _indexes.slice()},load(){_indexes.splice(0);const pfs=require("./promise-fs");if(!pfs||!pfs.readdir){return Promise.resolve()}return pfs.readdir(`${storage.settings.path}/${storage.name}.acebase`).then(files=>{const promises=[];files.forEach(fileName=>{if(fileName.endsWith(".idx")){const p=DataIndex.readFromFile(storage,fileName).then(index=>{_indexes.push(index)}).catch(err=>{storage.debug.error(err)});promises.push(p)}});return Promise.all(promises)}).catch(err=>{if(err.code!=="ENOENT"){storage.debug.error(err)}})}};const _subs={};const _supportedEvents=["value","child_added","child_changed","child_removed"];_supportedEvents.push(..._supportedEvents.map(event=>`notify_${event}`));this.subscriptions={add(path,type,callback){if(_supportedEvents.indexOf(type)<0){throw new TypeError(`Invalid event type "${type}"`)}let pathSubs=_subs[path];if(!pathSubs){pathSubs=_subs[path]=[]}pathSubs.push({created:Date.now(),type:type,callback:callback})},remove(path,type=undefined,callback=undefined){let pathSubs=_subs[path];if(!pathSubs){return}while(true){const i=pathSubs.findIndex(ps=>(type?ps.type===type:true)&&(callback?ps.callback===callback:true));if(i<0){break}pathSubs.splice(i,1)}},hasValueSubscribersForPath(path){const valueNeeded=this.getValueSubscribersForPath(path);return!!valueNeeded},getValueSubscribersForPath(path){const pathInfo=new PathInfo(path);const valueSubscribers=[];Object.keys(_subs).forEach(subscriptionPath=>{if(pathInfo.equals(subscriptionPath)||pathInfo.isDescendantOf(subscriptionPath)){let pathSubs=_subs[subscriptionPath];const eventPath=PathInfo.fillVariables(subscriptionPath,path);pathSubs.forEach(sub=>{let dataPath=null;if(sub.type==="value"||sub.type==="notify_value"){dataPath=eventPath}else if((sub.type==="child_changed"||sub.type==="notify_child_changed")&&path!==eventPath){let childKey=PathInfo.getPathKeys(path.slice(eventPath.length).replace(/^\//,""))[0];dataPath=PathInfo.getChildPath(eventPath,childKey)}else if(["child_added","child_removed","notify_child_added","notify_child_removed"].includes(sub.type)&&pathInfo.isChildOf(eventPath)){let childKey=PathInfo.getPathKeys(path.slice(eventPath.length).replace(/^\//,""))[0];dataPath=PathInfo.getChildPath(eventPath,childKey)}if(dataPath!==null&&valueSubscribers.findIndex(s=>s.type===sub.type&&s.path===eventPath)<0){valueSubscribers.push({type:sub.type,eventPath:eventPath,dataPath:dataPath,subscriptionPath:subscriptionPath})}})}});return valueSubscribers},getAllSubscribersForPath(path){const pathInfo=PathInfo.get(path);const subscribers=[];Object.keys(_subs).forEach(subscriptionPath=>{if(pathInfo.equals(subscriptionPath)||pathInfo.isDescendantOf(subscriptionPath)||pathInfo.isAncestorOf(subscriptionPath)){let pathSubs=_subs[subscriptionPath];const eventPath=PathInfo.fillVariables(subscriptionPath,path);pathSubs.forEach(sub=>{let dataPath=null;if(sub.type==="value"||sub.type==="notify_value"){dataPath=eventPath}else if(sub.type==="child_changed"||sub.type==="notify_child_changed"){let childKey=path===eventPath||pathInfo.isAncestorOf(eventPath)?"*":PathInfo.getPathKeys(path.slice(eventPath.length).replace(/^\//,""))[0];dataPath=PathInfo.getChildPath(eventPath,childKey)}else if(["child_added","child_removed","notify_child_added","notify_child_removed"].includes(sub.type)&&(pathInfo.isChildOf(eventPath)||path===eventPath||pathInfo.isAncestorOf(eventPath))){let childKey=path===eventPath||pathInfo.isAncestorOf(eventPath)?"*":PathInfo.getPathKeys(path.slice(eventPath.length).replace(/^\//,""))[0];dataPath=PathInfo.getChildPath(eventPath,childKey)}if(dataPath!==null&&!subscribers.some(s=>s.type===sub.type&&s.eventPath===eventPath)){subscribers.push({type:sub.type,eventPath:eventPath,dataPath:dataPath,subscriptionPath:subscriptionPath})}})}});return subscribers},trigger(event,path,dataPath,oldValue,newValue){const pathSubscriptions=_subs[path]||[];pathSubscriptions.filter(sub=>sub.type===event).forEach(sub=>{sub.callback(null,dataPath,newValue,oldValue)})}}}get path(){return`${this.settings.path}/${this.name}.acebase`}valueFitsInline(value){const encoding="utf8";if(typeof value==="number"||typeof value==="boolean"||value instanceof Date){return true}else if(typeof value==="string"){if(value.length>this.settings.maxInlineValueSize){return false}const encoded=encodeString(value);return encoded.lengththis.settings.maxInlineValueSize){return false}const encoded=encodeString(value.path);return encoded.length0){hasValueSubscribers=true;let eventPaths=valueSubscribers.map(sub=>{return{path:sub.dataPath,keys:PathInfo.getPathKeys(sub.dataPath)}}).sort((a,b)=>{if(a.keys.lengthb.keys.length)return 1;return 0});let first=eventPaths[0];topEventPath=first.path;if(valueSubscribers.filter(sub=>sub.dataPath===topEventPath).every(sub=>sub.type.startsWith("notify_"))){hasValueSubscribers=false}topEventPath=PathInfo.fillVariables(topEventPath,path)}const writeNode=()=>{if(typeof options._customWriteFunction==="function"){return options._customWriteFunction()}return this._writeNode(path,value,options)};const indexes=this.indexes.getAll(path,{childPaths:true,parentPaths:true}).map(index=>({index:index,keys:PathInfo.getPathKeys(index.path)})).sort((a,b)=>{if(a.keys.lengthb.keys.length){return 1}return 0}).map(obj=>obj.index);if(eventSubscriptions.length===0&&indexes.length===0){return writeNode()}let keysFilter=[];if(indexes.length>0){indexes.sort((a,b)=>{if(typeof a._pathKeys==="undefined"){a._pathKeys=PathInfo.getPathKeys(a.path)}if(typeof b._pathKeys==="undefined"){b._pathKeys=PathInfo.getPathKeys(b.path)}if(a._pathKeys.lengthb._pathKeys.length)return 1;return 0});const topIndex=indexes[0];let topIndexPath=topIndex.path===path?path:PathInfo.fillVariables(`${topIndex.path}/*`,path);if(topIndexPath.lengthindex.path===topIndex.path).forEach(index=>{let keys=[index.key].concat(index.includeKeys);keys.forEach(key=>!keysFilter.includes(key)&&keysFilter.push(key))})}}if(!hasValueSubscribers&&options.merge===true&&keysFilter.length===0){keysFilter=Object.keys(value);if(topEventPath!==path){let trailPath=path.slice(topEventPath.length);keysFilter=keysFilter.map(key=>`${trailPath}/${key}`)}}return this.getNodeInfo(topEventPath,{transaction:transaction,tid:tid}).then(eventNodeInfo=>{if(!eventNodeInfo.exists){return null}let valueOptions={transaction:transaction,tid:tid};if(keysFilter.length>0){valueOptions.include=keysFilter}if(topEventPath===""&&typeof valueOptions.include==="undefined"){this.debug.warn(`WARNING: One or more value event listeners on the root node are causing the entire database value to be read to facilitate change tracking. Using "value", "notify_value", "child_changed" and "notify_child_changed" events on the root node are a bad practice because of the significant performance impact`)}return this.getNodeValue(topEventPath,valueOptions)}).then(currentValue=>{topEventData=currentValue;return writeNode()}).then(result=>{let newTopEventData=cloneObject(topEventData);if(newTopEventData===null){newTopEventData=path===topEventPath?value:{}}let modifiedData=newTopEventData;if(path!==topEventPath){let trailPath=path.slice(topEventPath.length).replace(/^\//,"");let trailKeys=PathInfo.getPathKeys(trailPath);while(trailKeys.length>0){let childKey=trailKeys.shift();if(!options.merge&&trailKeys.length===0){modifiedData[childKey]=value}else{if(!(childKey in modifiedData)){modifiedData[childKey]={}}modifiedData=modifiedData[childKey]}}}if(options.merge){Object.keys(value).forEach(key=>{let newValue=value[key];if(newValue!==null){modifiedData[key]=newValue}else{delete modifiedData[key]}})}else if(path===topEventPath){newTopEventData=modifiedData=value}const indexUpdates=[];indexes.map(index=>({index:index,keys:PathInfo.getPathKeys(index.path)})).sort((a,b)=>{if(a.keys.lengthb.keys.length){return-1}return 0}).forEach(({index:index})=>{let pathKeys=PathInfo.getPathKeys(topEventPath);let indexPathKeys=PathInfo.getPathKeys(index.path+"/*");let trailKeys=indexPathKeys.slice(pathKeys.length);let oldValue=topEventData;let newValue=newTopEventData;if(trailKeys.length===0){console.assert(pathKeys.length===indexPathKeys.length,"check logic");const p=index.handleRecordUpdate(topEventPath,oldValue,newValue);indexUpdates.push(p);return}const getAllIndexUpdates=(path,oldValue,newValue)=>{if(oldValue===null&&newValue===null){return[]}let pathKeys=PathInfo.getPathKeys(path);let indexPathKeys=PathInfo.getPathKeys(index.path+"/*");let trailKeys=indexPathKeys.slice(pathKeys.length);if(trailKeys.length===0){console.assert(pathKeys.length===indexPathKeys.length,"check logic");return[{path:path,oldValue:oldValue,newValue:newValue}]}let results=[];let trailPath="";while(trailKeys.length>0){let subKey=trailKeys.shift();if(subKey==="*"){let allKeys=oldValue===null?[]:Object.keys(oldValue);newValue!==null&&Object.keys(newValue).forEach(key=>{if(allKeys.indexOf(key)<0){allKeys.push(key)}});allKeys.forEach(key=>{let childPath=PathInfo.getChildPath(trailPath,key);let childValues=getChildValues(key,oldValue,newValue);let subTrailPath=PathInfo.getChildPath(path,childPath);let childResults=getAllIndexUpdates(subTrailPath,childValues.oldValue,childValues.newValue);results=results.concat(childResults)});break}else{let values=getChildValues(subKey,oldValue,newValue);oldValue=values.oldValue;newValue=values.newValue;if(oldValue===null&&newValue===null){break}trailPath=PathInfo.getChildPath(trailPath,subKey)}}return results};let results=getAllIndexUpdates(topEventPath,oldValue,newValue);results.forEach(result=>{const p=index.handleRecordUpdate(result.path,result.oldValue,result.newValue);indexUpdates.push(p)})});const callSubscriberWithValues=(sub,oldValue,newValue,variables=[])=>{let trigger=true;let type=sub.type;if(type.startsWith("notify_")){type=type.slice("notify_".length)}if(type==="child_changed"&&(oldValue===null||newValue===null)){trigger=false}else if(type==="value"||type==="child_changed"){let changes=compareValues(oldValue,newValue);trigger=changes!=="identical"}else if(type==="child_added"){trigger=oldValue===null&&newValue!==null}else if(type==="child_removed"){trigger=oldValue!==null&&newValue===null}let dataPath=sub.dataPath;variables.forEach((variable,i)=>{const safeVarName=variable.name==="*"?"\\*":variable.name.replace("$","\\$");dataPath=dataPath.replace(new RegExp(`(^|/)${safeVarName}([/[]|$)`),`$1${variable.value}$2`)});trigger&&this.subscriptions.trigger(sub.type,sub.subscriptionPath,dataPath,oldValue,newValue)};const triggerAllEvents=()=>{eventSubscriptions.map(sub=>{const keys=PathInfo.getPathKeys(sub.dataPath);return{sub:sub,keys:keys}}).sort((a,b)=>{if(a.keys.lengthb.keys.length){return-1}return 0}).forEach(({sub:sub})=>{const process=(currentPath,oldValue,newValue,variables=[])=>{let trailPath=sub.dataPath.slice(currentPath.length).replace(/^\//,"");let trailKeys=PathInfo.getPathKeys(trailPath);while(trailKeys.length>0){let subKey=trailKeys.shift();if(typeof subKey==="string"&&(subKey==="*"||subKey[0]==="$")){let allKeys=oldValue===null?[]:Object.keys(oldValue);newValue!==null&&Object.keys(newValue).forEach(key=>{if(allKeys.indexOf(key)<0){allKeys.push(key)}});allKeys.forEach(key=>{const childValues=getChildValues(key,oldValue,newValue);const vars=variables.concat({name:subKey,value:key});if(trailKeys.length===0){callSubscriberWithValues(sub,childValues.oldValue,childValues.newValue,vars)}else{process(`${currentPath}/${subKey}`,childValues.oldValue,childValues.newValue,vars)}});return}else{currentPath=PathInfo.getChildPath(currentPath,subKey);let childValues=getChildValues(subKey,oldValue,newValue);oldValue=childValues.oldValue;newValue=childValues.newValue}}callSubscriberWithValues(sub,oldValue,newValue,variables)};process(topEventPath,topEventData,newTopEventData)})};if(options.waitForIndexUpdates===false){indexUpdates.splice(0)}return Promise.all(indexUpdates).then(()=>{process.nextTick(triggerAllEvents);return result})})}getChildren(path,options={keyFilter:undefined,tid:undefined}){throw new Error(`This method must be implemented by subclass`)}getNodeValue(path,options={include:undefined,exclude:undefined,child_objects:true,tid:undefined}){return this.getNode(path,options).then(node=>{return node.value})}getNode(path,options={include:undefined,exclude:undefined,child_objects:true,tid:undefined}){throw new Error(`This method must be implemented by subclass`)}getNodeInfo(path,options={tid:undefined}){throw new Error(`This method must be implemented by subclass`)}removeNode(path,options={tid:undefined}){throw new Error(`This method must be implemented by subclass`)}setNode(path,value,options={tid:undefined}){throw new Error(`This method must be implemented by subclass`)}updateNode(path,updates,options={tid:undefined}){throw new Error(`This method must be implemented by subclass`)}transactNode(path,callback,options={no_lock:false}){let checkRevision;const tid=ID.generate();const lockPromise=options&&options.no_lock===true?Promise.resolve({tid:tid,release(){}}):this.nodeLocker.lock(path,tid,true,"transactNode");return lockPromise.then(lock=>{let changed=false,changeCallback=(err,path)=>{changed=true};if(options&&options.no_lock){this.subscriptions.add(path,"notify_value",changeCallback)}return this.getNode(path,{tid:tid}).then(node=>{checkRevision=node.revision;let newValue;try{newValue=callback(node.value)}catch(err){this.debug.error(`Error in transaction callback: ${err.message}`)}if(newValue instanceof Promise){return newValue.catch(err=>{this.debug.error(`Error in transaction callback: ${err.message}`)})}return newValue}).then(newValue=>{if(typeof newValue==="undefined"){return}if(options&&options.no_lock){this.subscriptions.remove(path,"notify_value",changeCallback)}if(changed){return Promise.reject(new NodeRevisionError(`Node changed`))}return this.setNode(path,newValue,{assert_revision:checkRevision,tid:lock.tid})}).then(result=>{lock.release();return result}).catch(err=>{lock.release();if(err instanceof NodeRevisionError){console.warn(`node value changed, running again. Error: ${err.message}`);return this.transactNode(path,callback,options)}else{throw err}})})}matchNode(path,criteria,options={tid:undefined}){const tid=options&&options.tid||ID.generate();const checkNode=(path,criteria)=>{if(criteria.length===0){return Promise.resolve(true)}const criteriaKeys=criteria.reduce((keys,cr)=>{if(keys.indexOf(cr.key)<0){keys.push(cr.key)}return keys},[]);const unseenKeys=criteriaKeys.slice();let isMatch=true;let delayedMatchPromises=[];return this.getChildren(path,{tid:tid,keyFilter:criteriaKeys}).next(childInfo=>{unseenKeys.includes(childInfo.key)&&unseenKeys.splice(unseenKeys.indexOf(childInfo.key),1);const keyCriteria=criteria.filter(cr=>cr.key===childInfo.key).map(cr=>({op:cr.op,compare:cr.compare}));const result=checkChild(childInfo,keyCriteria);isMatch=result.isMatch;delayedMatchPromises.push(...result.promises);if(!isMatch||unseenKeys.length===0){return false}}).then(()=>{if(isMatch){return Promise.all(delayedMatchPromises).then(results=>{isMatch=results.every(res=>res.isMatch)})}}).then(()=>{if(!isMatch){return false}isMatch=unseenKeys.every(key=>{const child=new NodeInfo({key:key,exists:false});const keyCriteria=criteria.filter(cr=>cr.key===key).map(cr=>({op:cr.op,compare:cr.compare}));const result=checkChild(child,keyCriteria);return result.isMatch});return isMatch}).catch(err=>{this.debug.error(`Error matching on "${path}": `,err);throw err})};const checkChild=(child,criteria)=>{const promises=[];const isMatch=criteria.every(f=>{let proceed=true;if(f.op==="!exists"||f.op==="=="&&(typeof f.compare==="undefined"||f.compare===null)){proceed=!child.exists}else if(f.op==="exists"||f.op==="!="&&(typeof f.compare==="undefined"||f.compare===null)){proceed=child.exists}else if(!child.exists){proceed=false}else{if(child.address){if(child.valueType===VALUE_TYPES.OBJECT&&["has","!has"].indexOf(f.op)>=0){const op=f.op==="has"?"exists":"!exists";const p=checkNode(child.path,[{key:f.compare,op:op}]).then(isMatch=>{return{key:child.key,isMatch:isMatch}});promises.push(p);proceed=true}else if(child.valueType===VALUE_TYPES.ARRAY&&["contains","!contains"].indexOf(f.op)>=0){const p=this.getNodeValue(child.path,{tid:tid}).then(arr=>{const isMatch=f.op==="contains"?f.compare instanceof Array?f.compare.every(val=>arr.includes(val)):arr.includes(f.compare):f.compare instanceof Array?!f.compare.some(val=>arr.includes(val)):!arr.includes(f.compare);return{key:child.key,isMatch:isMatch}});promises.push(p);proceed=true}else if(child.valueType===VALUE_TYPES.STRING){const p=this.getNodeValue(child.path,{tid:tid}).then(val=>{return{key:child.key,isMatch:this.test(val,f.op,f.compare)}});promises.push(p);proceed=true}else{proceed=false}}else if(child.type===VALUE_TYPES.OBJECT&&["has","!has"].indexOf(f.op)>=0){const has=f.compare in child.value;proceed=has&&f.op==="has"||!has&&f.op==="!has"}else if(child.type===VALUE_TYPES.ARRAY&&["contains","!contains"].indexOf(f.op)>=0){const contains=child.value.indexOf(f.compare)>=0;proceed=contains&&f.op==="contains"||!contains&&f.op==="!contains"}else{const ret=this.test(child.value,f.op,f.compare);if(ret instanceof Promise){promises.push(ret);ret=true}proceed=ret}}return proceed});return{isMatch:isMatch,promises:promises}};return checkNode(path,criteria)}test(val,op,compare){if(op==="<"){return val"){return val>compare}if(op===">="){return val>=compare}if(op==="in"){return compare.indexOf(val)>=0}if(op==="!in"){return compare.indexOf(val)<0}if(op==="like"||op==="!like"){const pattern="^"+compare.replace(/[-[\]{}()+.,\\^$|#\s]/g,"\\$&").replace(/\?/g,".").replace(/\*/g,".*?")+"$";const re=new RegExp(pattern,"i");const isMatch=re.test(val.toString());return op==="like"?isMatch:!isMatch}if(op==="matches"){return compare.test(val.toString())}if(op==="!matches"){return!compare.test(val.toString())}if(op==="between"){return val>=compare[0]&&val<=compare[1]}if(op==="!between"){return valcompare[1]}if(op==="has"||op==="!has"){const has=typeof val==="object"&&compare in val;return op==="has"?has:!has}if(op==="contains"||op==="!contains"){const includes=typeof val==="object"&&val instanceof Array&&val.includes(compare);return op==="contains"?includes:!includes}return false}exportNode(path,stream,options={format:"json"}){if(options&&options.format!=="json"){throw new Error(`Only json output is currently supported`)}const stringifyValue=(type,val)=>{const escape=str=>str.replace(/\\/i,"\\\\").replace(/"/g,'\\"');if(type===VALUE_TYPES.DATETIME){val=`"${val.toISOString()}"`}else if(type===VALUE_TYPES.STRING){val=`"${escape(val)}"`}else if(type===VALUE_TYPES.ARRAY){val=`[]`}else if(type===VALUE_TYPES.OBJECT){val=`{}`}else if(type===VALUE_TYPES.BINARY){val=`"${escape(ascii85.encode(val))}"`}else if(type===VALUE_TYPES.REFERENCE){val=`"${val.path}"`}return val};const queue=[];let outputCount=0;let objStart="",objEnd="";const buffer={output:"",enable:false,promise:null};return this.getNodeInfo(path).then(nodeInfo=>{if(!nodeInfo.exists){stream.write("null")}else if(nodeInfo.type===VALUE_TYPES.OBJECT){objStart="{";objEnd="}"}else if(nodeInfo.type===VALUE_TYPES.ARRAY){objStart="{";objEnd="}"}else{return this.getNodeValue(path).then(value=>{const val=stringifyValue(nodeInfo.type,value);return stream.write(val)})}let p=Promise.resolve();if(objStart){p=stream.write(objStart);if(!(p instanceof Promise)){p=Promise.resolve()}}return p.then(()=>{return this.getChildren(path).next(childInfo=>{if(childInfo.address){queue.push(childInfo)}else{const val=stringifyValue(childInfo.type,childInfo.value);const comma=outputCount>0?",":"";const key=typeof childInfo.index==="number"?`"${childInfo.index}"`:`"${childInfo.key}"`;const output=`${comma}${key}:${val}`;outputCount++;if(buffer.enable){buffer.output+=output}else{const flush=output=>{const p=stream.write(output);if(p instanceof Promise){buffer.enable=true;buffer.promise=p.then(()=>{const buffered=buffer.output;buffer.enable=false;buffer.output="";buffer.promise=null;if(buffered.length>0){return flush(buffered)}});return buffer.promise}};flush(output)}}})})}).then(()=>{return buffer.promise}).then(()=>{const next=()=>{if(queue.length===0){return}const childInfo=queue.shift();const comma=outputCount>0?",":"";const key=typeof childInfo.index==="number"?`"${childInfo.index}"`:`"${childInfo.key}"`;let p=stream.write(`${comma}${key}:`);outputCount++;if(!(p instanceof Promise)){p=Promise.resolve(p)}return p.then(()=>{return this.exportNode(childInfo.address.path,stream)}).then(()=>{return next()})};return next()}).then(()=>{if(objEnd){return stream.write(objEnd)}})}}module.exports={Storage:Storage,StorageSettings:StorageSettings,NodeNotFoundError:NodeNotFoundError,NodeRevisionError:NodeRevisionError}}).call(this,require("_process"))},{"./data-index":40,"./node-info":34,"./node-lock":35,"./node-value-types":36,"./promise-fs":40,_process:44,"acebase-core":11,colors:22,events:41}],40:[function(require,module,exports){},{}],41:[function(require,module,exports){var objectCreate=Object.create||objectCreatePolyfill;var objectKeys=Object.keys||objectKeysPolyfill;var bind=Function.prototype.bind||functionBindPolyfill;function EventEmitter(){if(!this._events||!Object.prototype.hasOwnProperty.call(this,"_events")){this._events=objectCreate(null);this._eventsCount=0}this._maxListeners=this._maxListeners||undefined}module.exports=EventEmitter;EventEmitter.EventEmitter=EventEmitter;EventEmitter.prototype._events=undefined;EventEmitter.prototype._maxListeners=undefined;var defaultMaxListeners=10;var hasDefineProperty;try{var o={};if(Object.defineProperty)Object.defineProperty(o,"x",{value:0});hasDefineProperty=o.x===0}catch(err){hasDefineProperty=false}if(hasDefineProperty){Object.defineProperty(EventEmitter,"defaultMaxListeners",{enumerable:true,get:function(){return defaultMaxListeners},set:function(arg){if(typeof arg!=="number"||arg<0||arg!==arg)throw new TypeError('"defaultMaxListeners" must be a positive number');defaultMaxListeners=arg}})}else{EventEmitter.defaultMaxListeners=defaultMaxListeners}EventEmitter.prototype.setMaxListeners=function setMaxListeners(n){if(typeof n!=="number"||n<0||isNaN(n))throw new TypeError('"n" argument must be a positive number');this._maxListeners=n;return this};function $getMaxListeners(that){if(that._maxListeners===undefined)return EventEmitter.defaultMaxListeners;return that._maxListeners}EventEmitter.prototype.getMaxListeners=function getMaxListeners(){return $getMaxListeners(this)};function emitNone(handler,isFn,self){if(isFn)handler.call(self);else{var len=handler.length;var listeners=arrayClone(handler,len);for(var i=0;i1)er=arguments[1];if(er instanceof Error){throw er}else{var err=new Error('Unhandled "error" event. ('+er+")");err.context=er;throw err}return false}handler=events[type];if(!handler)return false;var isFn=typeof handler==="function";len=arguments.length;switch(len){case 1:emitNone(handler,isFn,this);break;case 2:emitOne(handler,isFn,this,arguments[1]);break;case 3:emitTwo(handler,isFn,this,arguments[1],arguments[2]);break;case 4:emitThree(handler,isFn,this,arguments[1],arguments[2],arguments[3]);break;default:args=new Array(len-1);for(i=1;i0&&existing.length>m){existing.warned=true;var w=new Error("Possible EventEmitter memory leak detected. "+existing.length+' "'+String(type)+'" listeners '+"added. Use emitter.setMaxListeners() to "+"increase limit.");w.name="MaxListenersExceededWarning";w.emitter=target;w.type=type;w.count=existing.length;if(typeof console==="object"&&console.warn){console.warn("%s: %s",w.name,w.message)}}}}return target}EventEmitter.prototype.addListener=function addListener(type,listener){return _addListener(this,type,listener,false)};EventEmitter.prototype.on=EventEmitter.prototype.addListener;EventEmitter.prototype.prependListener=function prependListener(type,listener){return _addListener(this,type,listener,true)};function onceWrapper(){if(!this.fired){this.target.removeListener(this.type,this.wrapFn);this.fired=true;switch(arguments.length){case 0:return this.listener.call(this.target);case 1:return this.listener.call(this.target,arguments[0]);case 2:return this.listener.call(this.target,arguments[0],arguments[1]);case 3:return this.listener.call(this.target,arguments[0],arguments[1],arguments[2]);default:var args=new Array(arguments.length);for(var i=0;i=0;i--){if(list[i]===listener||list[i].listener===listener){originalListener=list[i].listener;position=i;break}}if(position<0)return this;if(position===0)list.shift();else spliceOne(list,position);if(list.length===1)events[type]=list[0];if(events.removeListener)this.emit("removeListener",type,originalListener||listener)}return this};EventEmitter.prototype.removeAllListeners=function removeAllListeners(type){var listeners,events,i;events=this._events;if(!events)return this;if(!events.removeListener){if(arguments.length===0){this._events=objectCreate(null);this._eventsCount=0}else if(events[type]){if(--this._eventsCount===0)this._events=objectCreate(null);else delete events[type]}return this}if(arguments.length===0){var keys=objectKeys(events);var key;for(i=0;i=0;i--){this.removeListener(type,listeners[i])}}return this};function _listeners(target,type,unwrap){var events=target._events;if(!events)return[];var evlistener=events[type];if(!evlistener)return[];if(typeof evlistener==="function")return unwrap?[evlistener.listener||evlistener]:[evlistener];return unwrap?unwrapListeners(evlistener):arrayClone(evlistener,evlistener.length)}EventEmitter.prototype.listeners=function listeners(type){return _listeners(this,type,true)};EventEmitter.prototype.rawListeners=function rawListeners(type){return _listeners(this,type,false)};EventEmitter.listenerCount=function(emitter,type){if(typeof emitter.listenerCount==="function"){return emitter.listenerCount(type)}else{return listenerCount.call(emitter,type)}};EventEmitter.prototype.listenerCount=listenerCount;function listenerCount(type){var events=this._events;if(events){var evlistener=events[type];if(typeof evlistener==="function"){return 1}else if(evlistener){return evlistener.length}}return 0}EventEmitter.prototype.eventNames=function eventNames(){return this._eventsCount>0?Reflect.ownKeys(this._events):[]};function spliceOne(list,index){for(var i=index,k=i+1,n=list.length;k1){for(var i=1;i=len)return x;switch(x){case"%s":return String(args[i++]);case"%d":return Number(args[i++]);case"%j":try{return JSON.stringify(args[i++])}catch(_){return"[Circular]"}default:return x}}));for(var x=args[i];i=3)ctx.depth=arguments[2];if(arguments.length>=4)ctx.colors=arguments[3];if(isBoolean(opts)){ctx.showHidden=opts}else if(opts){exports._extend(ctx,opts)}if(isUndefined(ctx.showHidden))ctx.showHidden=false;if(isUndefined(ctx.depth))ctx.depth=2;if(isUndefined(ctx.colors))ctx.colors=false;if(isUndefined(ctx.customInspect))ctx.customInspect=true;if(ctx.colors)ctx.stylize=stylizeWithColor;return formatValue(ctx,obj,ctx.depth)}exports.inspect=inspect;inspect.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]};inspect.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"};function stylizeWithColor(str,styleType){var style=inspect.styles[styleType];if(style){return"["+inspect.colors[style][0]+"m"+str+"["+inspect.colors[style][1]+"m"}else{return str}}function stylizeNoColor(str,styleType){return str}function arrayToHash(array){var hash={};array.forEach((function(val,idx){hash[val]=true}));return hash}function formatValue(ctx,value,recurseTimes){if(ctx.customInspect&&value&&isFunction(value.inspect)&&value.inspect!==exports.inspect&&!(value.constructor&&value.constructor.prototype===value)){var ret=value.inspect(recurseTimes,ctx);if(!isString(ret)){ret=formatValue(ctx,ret,recurseTimes)}return ret}var primitive=formatPrimitive(ctx,value);if(primitive){return primitive}var keys=Object.keys(value);var visibleKeys=arrayToHash(keys);if(ctx.showHidden){keys=Object.getOwnPropertyNames(value)}if(isError(value)&&(keys.indexOf("message")>=0||keys.indexOf("description")>=0)){return formatError(value)}if(keys.length===0){if(isFunction(value)){var name=value.name?": "+value.name:"";return ctx.stylize("[Function"+name+"]","special")}if(isRegExp(value)){return ctx.stylize(RegExp.prototype.toString.call(value),"regexp")}if(isDate(value)){return ctx.stylize(Date.prototype.toString.call(value),"date")}if(isError(value)){return formatError(value)}}var base="",array=false,braces=["{","}"];if(isArray(value)){array=true;braces=["[","]"]}if(isFunction(value)){var n=value.name?": "+value.name:"";base=" [Function"+n+"]"}if(isRegExp(value)){base=" "+RegExp.prototype.toString.call(value)}if(isDate(value)){base=" "+Date.prototype.toUTCString.call(value)}if(isError(value)){base=" "+formatError(value)}if(keys.length===0&&(!array||value.length==0)){return braces[0]+base+braces[1]}if(recurseTimes<0){if(isRegExp(value)){return ctx.stylize(RegExp.prototype.toString.call(value),"regexp")}else{return ctx.stylize("[Object]","special")}}ctx.seen.push(value);var output;if(array){output=formatArray(ctx,value,recurseTimes,visibleKeys,keys)}else{output=keys.map((function(key){return formatProperty(ctx,value,recurseTimes,visibleKeys,key,array)}))}ctx.seen.pop();return reduceToSingleString(output,base,braces)}function formatPrimitive(ctx,value){if(isUndefined(value))return ctx.stylize("undefined","undefined");if(isString(value)){var simple="'"+JSON.stringify(value).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return ctx.stylize(simple,"string")}if(isNumber(value))return ctx.stylize(""+value,"number");if(isBoolean(value))return ctx.stylize(""+value,"boolean");if(isNull(value))return ctx.stylize("null","null")}function formatError(value){return"["+Error.prototype.toString.call(value)+"]"}function formatArray(ctx,value,recurseTimes,visibleKeys,keys){var output=[];for(var i=0,l=value.length;i-1){if(array){str=str.split("\n").map((function(line){return" "+line})).join("\n").substr(2)}else{str="\n"+str.split("\n").map((function(line){return" "+line})).join("\n")}}}else{str=ctx.stylize("[Circular]","special")}}if(isUndefined(name)){if(array&&key.match(/^\d+$/)){return str}name=JSON.stringify(""+key);if(name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)){name=name.substr(1,name.length-2);name=ctx.stylize(name,"name")}else{name=name.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'");name=ctx.stylize(name,"string")}}return name+": "+str}function reduceToSingleString(output,base,braces){var numLinesEst=0;var length=output.reduce((function(prev,cur){numLinesEst++;if(cur.indexOf("\n")>=0)numLinesEst++;return prev+cur.replace(/\u001b\[\d\d?m/g,"").length+1}),0);if(length>60){return braces[0]+(base===""?"":base+"\n ")+" "+output.join(",\n ")+" "+braces[1]}return braces[0]+base+" "+output.join(", ")+" "+braces[1]}function isArray(ar){return Array.isArray(ar)}exports.isArray=isArray;function isBoolean(arg){return typeof arg==="boolean"}exports.isBoolean=isBoolean;function isNull(arg){return arg===null}exports.isNull=isNull;function isNullOrUndefined(arg){return arg==null}exports.isNullOrUndefined=isNullOrUndefined;function isNumber(arg){return typeof arg==="number"}exports.isNumber=isNumber;function isString(arg){return typeof arg==="string"}exports.isString=isString;function isSymbol(arg){return typeof arg==="symbol"}exports.isSymbol=isSymbol;function isUndefined(arg){return arg===void 0}exports.isUndefined=isUndefined;function isRegExp(re){return isObject(re)&&objectToString(re)==="[object RegExp]"}exports.isRegExp=isRegExp;function isObject(arg){return typeof arg==="object"&&arg!==null}exports.isObject=isObject;function isDate(d){return isObject(d)&&objectToString(d)==="[object Date]"}exports.isDate=isDate;function isError(e){return isObject(e)&&(objectToString(e)==="[object Error]"||e instanceof Error)}exports.isError=isError;function isFunction(arg){return typeof arg==="function"}exports.isFunction=isFunction;function isPrimitive(arg){return arg===null||typeof arg==="boolean"||typeof arg==="number"||typeof arg==="string"||typeof arg==="symbol"||typeof arg==="undefined"}exports.isPrimitive=isPrimitive;exports.isBuffer=require("./support/isBuffer");function objectToString(o){return Object.prototype.toString.call(o)}function pad(n){return n<10?"0"+n.toString(10):n.toString(10)}var months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function timestamp(){var d=new Date;var time=[pad(d.getHours()),pad(d.getMinutes()),pad(d.getSeconds())].join(":");return[d.getDate(),months[d.getMonth()],time].join(" ")}exports.log=function(){console.log("%s - %s",timestamp(),exports.format.apply(exports,arguments))};exports.inherits=require("inherits");exports._extend=function(origin,add){if(!add||!isObject(add))return origin;var keys=Object.keys(add);var i=keys.length;while(i--){origin[keys[i]]=add[keys[i]]}return origin};function hasOwnProperty(obj,prop){return Object.prototype.hasOwnProperty.call(obj,prop)}}).call(this,require("_process"),typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./support/isBuffer":45,_process:44,inherits:42}]},{},[33])(33)})); \ No newline at end of file