From a6214ffecb1c434c0c724ca8d8398dde7c09fed0 Mon Sep 17 00:00:00 2001 From: Joelchu Date: Thu, 15 Aug 2019 13:21:06 +0800 Subject: [PATCH 1/9] update jsonql-koa deps and test again --- packages/koa/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/koa/package.json b/packages/koa/package.json index 2350cc7e..6957c709 100755 --- a/packages/koa/package.json +++ b/packages/koa/package.json @@ -44,11 +44,11 @@ "fs-extra": "^8.1.0", "jsonql-constants": "^1.7.9", "jsonql-contract": "^1.7.7", - "jsonql-errors": "^1.0.9", - "jsonql-jwt": "^1.2.4", + "jsonql-errors": "^1.1.1", + "jsonql-jwt": "^1.2.5", "jsonql-node-client": "^1.1.3", "jsonql-params-validator": "^1.4.3", - "jsonql-resolver": "^0.4.0", + "jsonql-resolver": "^0.5.0", "jsonql-web-console": "^0.4.3", "koa": "^2.7.0", "koa-compose": "^4.1.0", -- Gitee From 22c86f9b76d0581d7038374b068734cb635bff2f Mon Sep 17 00:00:00 2001 From: Joelchu Date: Thu, 15 Aug 2019 13:21:38 +0800 Subject: [PATCH 2/9] remove unused test files --- packages/koa/tests/fixtures/es/import.js | 2 -- packages/koa/tests/fixtures/es/resolver.js | 7 ------- 2 files changed, 9 deletions(-) delete mode 100644 packages/koa/tests/fixtures/es/import.js delete mode 100644 packages/koa/tests/fixtures/es/resolver.js diff --git a/packages/koa/tests/fixtures/es/import.js b/packages/koa/tests/fixtures/es/import.js deleted file mode 100644 index 6601f782..00000000 --- a/packages/koa/tests/fixtures/es/import.js +++ /dev/null @@ -1,2 +0,0 @@ -require = require("esm")(module/*, options*/) -module.exports = require("./resolver.js") diff --git a/packages/koa/tests/fixtures/es/resolver.js b/packages/koa/tests/fixtures/es/resolver.js deleted file mode 100644 index 9057792d..00000000 --- a/packages/koa/tests/fixtures/es/resolver.js +++ /dev/null @@ -1,7 +0,0 @@ -import querygetSomething from './query/get-something.js' -import mutationsaveSomething from './mutation/save-something.js' - -export { - querygetSomething, -mutationsaveSomething -} \ No newline at end of file -- Gitee From 630a0bd2830e423a7b216874fd59178352e934bd Mon Sep 17 00:00:00 2001 From: Joelchu Date: Thu, 15 Aug 2019 13:50:26 +0800 Subject: [PATCH 3/9] update the jsonql-jwt related methods --- packages/ws-client/dist/jsonql-ws-client.js | 1255 +++++++++-------- .../ws-client/dist/jsonql-ws-client.js.map | 2 +- packages/ws-client/package.json | 40 +- .../ws-client/src/node/client-generator.js | 9 +- packages/ws-client/src/node/main.cjs.js | 1255 +++++++++-------- .../ws-client/src/node/socketio-clients.js | 3 +- .../socketio-chain-connect-hs.test.js | 0 .../socketio-chain-connect-rt.test.js | 0 .../socketio-handshake.test.js | 0 .../socketio-roundtrip-fail.test.js | 0 .../socketio-roundtrip.test.js | 0 .../{connect => jwt}/ws-handshake.test.js | 0 12 files changed, 1432 insertions(+), 1132 deletions(-) rename packages/ws-client/tests/{connect => jwt}/socketio-chain-connect-hs.test.js (100%) rename packages/ws-client/tests/{connect => jwt}/socketio-chain-connect-rt.test.js (100%) rename packages/ws-client/tests/{connect => jwt}/socketio-handshake.test.js (100%) rename packages/ws-client/tests/{connect => jwt}/socketio-roundtrip-fail.test.js (100%) rename packages/ws-client/tests/{connect => jwt}/socketio-roundtrip.test.js (100%) rename packages/ws-client/tests/{connect => jwt}/ws-handshake.test.js (100%) diff --git a/packages/ws-client/dist/jsonql-ws-client.js b/packages/ws-client/dist/jsonql-ws-client.js index efacac0b..184f3458 100644 --- a/packages/ws-client/dist/jsonql-ws-client.js +++ b/packages/ws-client/dist/jsonql-ws-client.js @@ -81,7 +81,7 @@ var MESSAGE_PROP_NAME = 'onMessage'; var RESULT_PROP_NAME = 'onResult'; var ERROR_PROP_NAME = 'onError'; - var READY_PROP_NAME = 'onReady'; + var READY_PROP_NAME = 'onReady'; var SEND_MSG_PROP_NAME = 'send'; // this is the default time to wait for reply if exceed this then we // trigger an error --> 5 seconds @@ -4174,7 +4174,7 @@ } /** - * Gets the value at `key`, unless `key` is "__proto__". + * Gets the value at `key`, unless `key` is "__proto__" or "constructor". * * @private * @param {Object} object The object to query. @@ -4182,6 +4182,10 @@ * @returns {*} Returns the property value. */ function safeGet(object, key) { + if (key === 'constructor' && typeof object[key] === 'function') { + return; + } + if (key == '__proto__') { return; } @@ -4310,8 +4314,8 @@ return; } baseFor(source, function(srcValue, key) { + stack || (stack = new Stack); if (isObject(srcValue)) { - stack || (stack = new Stack); baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); } else { @@ -5687,21 +5691,31 @@ /** * @param {string} resolverName name of function * @param {array} [args=[]] from the ...args + * @param {boolean} [jsonp = false] add v1.3.0 to koa * @return {object} formatted argument */ - function createQuery(resolverName, args) { - var obj, obj$1; + function createQuery(resolverName, args, jsonp) { + var obj; if ( args === void 0 ) args = []; + if ( jsonp === void 0 ) jsonp = false; if (checkIsString(resolverName) && checkIsArray(args)) { - return ( obj$1 = {}, obj$1[resolverName] = ( obj = {}, obj[QUERY_ARG_NAME] = args, obj ), obj$1 ) + var payload = {}; + payload[QUERY_ARG_NAME] = args; + if (jsonp === true) { + return payload; + } + return ( obj = {}, obj[resolverName] = payload, obj ) } throw new JsonqlValidationError("[createQuery] expect resolverName to be string and args to be array!", { resolverName: resolverName, args: args }) } // string version of the above - function createQueryStr(resolverName, args) { - return JSON.stringify(createQuery(resolverName, args)) + function createQueryStr(resolverName, args, jsonp) { + if ( args === void 0 ) args = []; + if ( jsonp === void 0 ) jsonp = false; + + return JSON.stringify(createQuery(resolverName, args, jsonp)) } // export @@ -6089,630 +6103,763 @@ return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0) } - // this is the new implementation without the hash key - // export - var EventService = function EventService(config) { - if ( config === void 0 ) config = {}; - - if (config.logger && typeof config.logger === 'function') { - this.logger = config.logger; - } - this.keep = config.keep; - // for the $done setter - this.result = config.keep ? [] : null; - // we need to init the store first otherwise it could be a lot of checking later - this.normalStore = new Map(); - this.lazyStore = new Map(); + // making all the functionality on it's own + // import { WatchClass } from './watch' + + var SuspendClass = function SuspendClass() { + // suspend, release and queue + this.__suspend__ = null; + this.queueStore = new Set(); + /* + this.watch('suspend', function(value, prop, oldValue) { + this.logger(`${prop} set from ${oldValue} to ${value}`) + // it means it set the suspend = true then release it + if (oldValue === true && value === false) { + // we want this happen after the return happens + setTimeout(() => { + this.release() + }, 1) + } + return value; // we need to return the value to store it + }) + */ }; - var prototypeAccessors = { $done: { configurable: true },normalStore: { configurable: true },lazyStore: { configurable: true } }; - - /** - * logger function for overwrite - */ - EventService.prototype.logger = function logger () {}; - - ////////////////////////// - // PUBLIC METHODS // - ////////////////////////// + var prototypeAccessors = { $suspend: { configurable: true },$queues: { configurable: true } }; /** - * Register your evt handler, note we don't check the type here, - * we expect you to be sensible and know what you are doing. - * @param {string} evt name of event - * @param {function} callback bind method --> if it's array or not - * @param {object} [context=null] to execute this call in - * @return {number} the size of the store + * setter to set the suspend and check if it's boolean value + * @param {boolean} value to trigger */ - EventService.prototype.$on = function $on (evt , callback , context) { + prototypeAccessors.$suspend.set = function (value) { var this$1 = this; - if ( context === void 0 ) context = null; - var type = 'on'; - this.validate(evt, callback); - // first need to check if this evt is in lazy store - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register first then call later - if (lazyStoreContent === false) { - this.logger('$on', (evt + " callback is not in lazy store")); - // @TODO we need to check if there was other listener to this - // event and are they the same type then we could solve that - // register the different type to the same event name - - return this.addToNormalStore(evt, type, callback, context) - } - this.logger('$on', (evt + " found in lazy store")); - // this is when they call $trigger before register this callback - var size = 0; - lazyStoreContent.forEach(function (content) { - var payload = content[0]; - var ctx = content[1]; - var t = content[2]; - if (t && t !== type) { - throw new Error(("You are trying to register an event already been taken by other type: " + t)) + if (typeof value === 'boolean') { + var lastValue = this.__suspend__; + this.__suspend__ = value; + this.logger('($suspend)', ("Change from " + lastValue + " --> " + value)); + if (lastValue === true && value === false) { + setTimeout(function () { + this$1.release(); + }, 1); } - this$1.run(callback, payload, context || ctx); - size += this$1.addToNormalStore(evt, type, callback, context || ctx); - }); - return size; - }; - - /** - * once only registered it once, there is no overwrite option here - * @NOTE change in v1.3.0 $once can add multiple listeners - * but once the event fired, it will remove this event (see $only) - * @param {string} evt name - * @param {function} callback to execute - * @param {object} [context=null] the handler execute in - * @return {boolean} result - */ - EventService.prototype.$once = function $once (evt , callback , context) { - if ( context === void 0 ) context = null; - - this.validate(evt, callback); - var type = 'once'; - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register before call $trigger - var nStore = this.normalStore; - if (lazyStoreContent === false) { - this.logger('$once', (evt + " not in the lazy store")); - // v1.3.0 $once now allow to add multiple listeners - return this.addToNormalStore(evt, type, callback, context) } else { - // now this is the tricky bit - // there is a potential bug here that cause by the developer - // if they call $trigger first, the lazy won't know it's a once call - // so if in the middle they register any call with the same evt name - // then this $once call will be fucked - add this to the documentation - this.logger('$once', lazyStoreContent); - var list = Array.from(lazyStoreContent); - // should never have more than 1 - var ref = list[0]; - var payload = ref[0]; - var ctx = ref[1]; - var t = ref[2]; - if (t && t !== type) { - throw new Error(("You are trying to register an event already been taken by other type: " + t)) - } - this.run(callback, payload, context || ctx); - // remove this evt from store - this.$off(evt); + throw new Error("$suspend only accept Boolean value!") } }; /** - * This one event can only bind one callbackback - * @param {string} evt event name - * @param {function} callback event handler - * @param {object} [context=null] the context the event handler execute in - * @return {boolean} true bind for first time, false already existed + * queuing call up when it's in suspend mode + * @param {any} value + * @return {Boolean} true when added or false when it's not */ - EventService.prototype.$only = function $only (evt, callback, context) { - var this$1 = this; - if ( context === void 0 ) context = null; + SuspendClass.prototype.$queue = function $queue () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; - this.validate(evt, callback); - var type = 'only'; - var added = false; - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register before call $trigger - var nStore = this.normalStore; - if (!nStore.has(evt)) { - this.logger("$only", (evt + " add to store")); - added = this.addToNormalStore(evt, type, callback, context); - } - if (lazyStoreContent !== false) { - // there are data store in lazy store - this.logger('$only', (evt + " found data in lazy store to execute")); - var list = Array.from(lazyStoreContent); - // $only allow to trigger this multiple time on the single handler - list.forEach( function (l) { - var payload = l[0]; - var ctx = l[1]; - var t = l[2]; - if (t && t !== type) { - throw new Error(("You are trying to register an event already been taken by other type: " + t)) - } - this$1.run(callback, payload, context || ctx); - }); + if (this.__suspend__ === true) { + this.logger('($queue)', 'added to $queue', args); + // there shouldn't be any duplicate ... + this.queueStore.add(args); } - return added; + return this.__suspend__; }; /** - * $only + $once this is because I found a very subtile bug when we pass a - * resolver, rejecter - and it never fire because that's OLD adeed in v1.4.0 - * @param {string} evt event name - * @param {function} callback to call later - * @param {object} [context=null] exeucte context - * @return {void} + * a getter to get all the store queue + * @return {array} Set turn into Array before return */ - EventService.prototype.$onlyOnce = function $onlyOnce (evt, callback, context) { - if ( context === void 0 ) context = null; - - this.validate(evt, callback); - var type = 'onlyOnce'; - var added = false; - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register before call $trigger - var nStore = this.normalStore; - if (!nStore.has(evt)) { - this.logger("$onlyOnce", (evt + " add to store")); - added = this.addToNormalStore(evt, type, callback, context); - } - if (lazyStoreContent !== false) { - // there are data store in lazy store - this.logger('$onlyOnce', lazyStoreContent); - var list = Array.from(lazyStoreContent); - // should never have more than 1 - var ref = list[0]; - var payload = ref[0]; - var ctx = ref[1]; - var t = ref[2]; - if (t && t !== 'onlyOnce') { - throw new Error(("You are trying to register an event already been taken by other type: " + t)) - } - this.run(callback, payload, context || ctx); - // remove this evt from store - this.$off(evt); + prototypeAccessors.$queues.get = function () { + var size = this.queueStore.size; + this.logger('($queues)', ("size: " + size)); + if (size > 0) { + return Array.from(this.queueStore) } - return added; + return [] }; /** - * This is a shorthand of $off + $on added in V1.5.0 - * @param {string} evt event name - * @param {function} callback to exeucte - * @param {object} [context = null] or pass a string as type - * @param {string} [type=on] what type of method to replace - * @return {} + * Release the queue + * @return {int} size if any */ - EventService.prototype.$replace = function $replace (evt, callback, context, type) { - if ( context === void 0 ) context = null; - if ( type === void 0 ) type = 'on'; + SuspendClass.prototype.release = function release () { + var this$1 = this; - if (this.validateType(type)) { - this.$off(evt); - var method = this['$' + type]; - return Reflect.apply(method, this, [evt, callback, context]) + var size = this.queueStore.size; + this.logger('(release)', ("Release was called " + size)); + if (size > 0) { + var queue = Array.from(this.queueStore); + this.queueStore.clear(); + this.logger('queue', queue); + queue.forEach(function (args) { + this$1.logger(args); + Reflect.apply(this$1.$trigger, this$1, args); + }); + this.logger(("Release size " + (this.queueStore.size))); } - throw new Error((type + " is not supported!")) }; - /** - * trigger the event - * @param {string} evt name NOT allow array anymore! - * @param {mixed} [payload = []] pass to fn - * @param {object|string} [context = null] overwrite what stored - * @param {string} [type=false] if pass this then we need to add type to store too - * @return {number} if it has been execute how many times - */ - EventService.prototype.$trigger = function $trigger (evt , payload , context, type) { - if ( payload === void 0 ) payload = []; - if ( context === void 0 ) context = null; - if ( type === void 0 ) type = false; + Object.defineProperties( SuspendClass.prototype, prototypeAccessors ); - this.validateEvt(evt); - var found = 0; - // first check the normal store - var nStore = this.normalStore; - this.logger('$trigger', nStore); - if (nStore.has(evt)) { - this.logger('$trigger', evt, 'found'); - var nSet = Array.from(nStore.get(evt)); - var ctn = nSet.length; - var hasOnce = false; - for (var i=0; i < ctn; ++i) { - ++found; - // this.logger('found', found) - var ref = nSet[i]; - var _ = ref[0]; - var callback = ref[1]; - var ctx = ref[2]; - var type$1 = ref[3]; - this.run(callback, payload, context || ctx); - if (type$1 === 'once' || type$1 === 'onlyOnce') { - hasOnce = true; - } - } - if (hasOnce) { - nStore.delete(evt); - } - return found; - } - // now this is not register yet - this.addToLazyStore(evt, payload, context, type); - return found; - }; + // break up the main file because its getting way too long - /** - * this is an alias to the $trigger - * @NOTE breaking change in V1.6.0 we swap the parameter around - * @param {string} evt event name - * @param {*} params pass to the callback - * @param {string} type of call - * @param {object} context what context callback execute in - * @return {*} from $trigger - */ - EventService.prototype.$call = function $call (evt, params, type, context) { - if ( type === void 0 ) type = false; - if ( context === void 0 ) context = null; - - var args = [evt, params]; - args.push(context, type); - return Reflect.apply(this.$trigger, this, args) - }; + var NbEventServiceBase = /*@__PURE__*/(function (SuspendClass) { + function NbEventServiceBase(config) { + if ( config === void 0 ) config = {}; - /** - * remove the evt from all the stores - * @param {string} evt name - * @return {boolean} true actually delete something - */ - EventService.prototype.$off = function $off (evt) { - this.validateEvt(evt); - var stores = [ this.lazyStore, this.normalStore ]; - var found = false; - stores.forEach(function (store) { - if (store.has(evt)) { - found = true; - store.delete(evt); + SuspendClass.call(this); + if (config.logger && typeof config.logger === 'function') { + this.logger = config.logger; } - }); - return found; - }; - - /** - * return all the listener from the event - * @param {string} evtName event name - * @param {boolean} [full=false] if true then return the entire content - * @return {array|boolean} listerner(s) or false when not found - */ - EventService.prototype.$get = function $get (evt, full) { - if ( full === void 0 ) full = false; - - this.validateEvt(evt); - var store = this.normalStore; - if (store.has(evt)) { - return Array - .from(store.get(evt)) - .map( function (l) { - if (full) { - return l; - } - var key = l[0]; - var callback = l[1]; - return callback; - }) + this.keep = config.keep; + // for the $done setter + this.result = config.keep ? [] : null; + // we need to init the store first otherwise it could be a lot of checking later + this.normalStore = new Map(); + this.lazyStore = new Map(); } - return false; - }; - /** - * store the return result from the run - * @param {*} value whatever return from callback - */ - prototypeAccessors.$done.set = function (value) { - this.logger('set $done', value); - if (this.keep) { - this.result.push(value); - } else { - this.result = value; - } - }; + if ( SuspendClass ) NbEventServiceBase.__proto__ = SuspendClass; + NbEventServiceBase.prototype = Object.create( SuspendClass && SuspendClass.prototype ); + NbEventServiceBase.prototype.constructor = NbEventServiceBase; - /** - * @TODO is there any real use with the keep prop? - * getter for $done - * @return {*} whatever last store result - */ - prototypeAccessors.$done.get = function () { - if (this.keep) { - this.logger(this.result); - return this.result[this.result.length - 1] - } - return this.result; - }; + var prototypeAccessors = { normalStore: { configurable: true },lazyStore: { configurable: true } }; - ///////////////////////////// - // PRIVATE METHODS // - ///////////////////////////// + /** + * validate the event name(s) + * @param {string[]} evt event name + * @return {boolean} true when OK + */ + NbEventServiceBase.prototype.validateEvt = function validateEvt () { + var this$1 = this; + var evt = [], len = arguments.length; + while ( len-- ) evt[ len ] = arguments[ len ]; - /** - * validate the event name - * @param {string} evt event name - * @return {boolean} true when OK - */ - EventService.prototype.validateEvt = function validateEvt (evt) { - if (typeof evt === 'string') { + evt.forEach(function (e) { + if (typeof e !== 'string') { + this$1.logger('(validateEvt)', e); + throw new Error("event name must be string type!") + } + }); return true; - } - throw new Error("event name must be string type!") - }; + }; - /** - * Simple quick check on the two main parameters - * @param {string} evt event name - * @param {function} callback function to call - * @return {boolean} true when OK - */ - EventService.prototype.validate = function validate (evt, callback) { - if (this.validateEvt(evt)) { - if (typeof callback === 'function') { - return true; + /** + * Simple quick check on the two main parameters + * @param {string} evt event name + * @param {function} callback function to call + * @return {boolean} true when OK + */ + NbEventServiceBase.prototype.validate = function validate (evt, callback) { + if (this.validateEvt(evt)) { + if (typeof callback === 'function') { + return true; + } } - } - throw new Error("callback required to be function type!") - }; + throw new Error("callback required to be function type!") + }; - /** - * Check if this type is correct or not added in V1.5.0 - * @param {string} type for checking - * @return {boolean} true on OK - */ - EventService.prototype.validateType = function validateType (type) { - var types = ['on', 'only', 'once', 'onlyOnce']; - return !!types.filter(function (t) { return type === t; }).length; - }; + /** + * Check if this type is correct or not added in V1.5.0 + * @param {string} type for checking + * @return {boolean} true on OK + */ + NbEventServiceBase.prototype.validateType = function validateType (type) { + var types = ['on', 'only', 'once', 'onlyOnce']; + return !!types.filter(function (t) { return type === t; }).length; + }; - /** - * Run the callback - * @param {function} callback function to execute - * @param {array} payload for callback - * @param {object} ctx context or null - * @return {void} the result store in $done - */ - EventService.prototype.run = function run (callback, payload, ctx) { - this.logger('run', callback, payload, ctx); - this.$done = Reflect.apply(callback, ctx, this.toArray(payload)); - }; + /** + * Run the callback + * @param {function} callback function to execute + * @param {array} payload for callback + * @param {object} ctx context or null + * @return {void} the result store in $done + */ + NbEventServiceBase.prototype.run = function run (callback, payload, ctx) { + this.logger('(run)', callback, payload, ctx); + this.$done = Reflect.apply(callback, ctx, this.toArray(payload)); + }; - /** - * Take the content out and remove it from store id by the name - * @param {string} evt event name - * @param {string} [storeName = lazyStore] name of store - * @return {object|boolean} content or false on not found - */ - EventService.prototype.takeFromStore = function takeFromStore (evt, storeName) { + /** + * Take the content out and remove it from store id by the name + * @param {string} evt event name + * @param {string} [storeName = lazyStore] name of store + * @return {object|boolean} content or false on not found + */ + NbEventServiceBase.prototype.takeFromStore = function takeFromStore (evt, storeName) { if ( storeName === void 0 ) storeName = 'lazyStore'; - var store = this[storeName]; // it could be empty at this point - if (store) { - this.logger('takeFromStore', storeName, store); - if (store.has(evt)) { - var content = store.get(evt); - this.logger('takeFromStore', content); - store.delete(evt); - return content; + var store = this[storeName]; // it could be empty at this point + if (store) { + this.logger('(takeFromStore)', storeName, store); + if (store.has(evt)) { + var content = store.get(evt); + this.logger('(takeFromStore)', ("has " + evt), content); + store.delete(evt); + return content; + } + return false; } - return false; - } - throw new Error((storeName + " is not supported!")) - }; + throw new Error((storeName + " is not supported!")) + }; - /** - * The add to store step is similar so make it generic for resuse - * @param {object} store which store to use - * @param {string} evt event name - * @param {spread} args because the lazy store and normal store store different things - * @return {array} store and the size of the store - */ - EventService.prototype.addToStore = function addToStore (store, evt) { + /** + * The add to store step is similar so make it generic for resuse + * @param {object} store which store to use + * @param {string} evt event name + * @param {spread} args because the lazy store and normal store store different things + * @return {array} store and the size of the store + */ + NbEventServiceBase.prototype.addToStore = function addToStore (store, evt) { var args = [], len = arguments.length - 2; while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; - var fnSet; - if (store.has(evt)) { - this.logger('addToStore', (evt + " existed")); - fnSet = store.get(evt); - } else { - this.logger('addToStore', ("create new Set for " + evt)); - // this is new - fnSet = new Set(); - } - // lazy only store 2 items - this is not the case in V1.6.0 anymore - // we need to check the first parameter is string or not - if (args.length > 2) { - if (Array.isArray(args[0])) { // lazy store - // check if this type of this event already register in the lazy store - var t = args[2]; - if (!this.checkTypeInLazyStore(evt, t)) { - fnSet.add(args); - } + var fnSet; + if (store.has(evt)) { + this.logger('(addToStore)', (evt + " existed")); + fnSet = store.get(evt); } else { - if (!this.checkContentExist(args, fnSet)) { - this.logger('addToStore', "insert new", args); - fnSet.add(args); + this.logger('(addToStore)', ("create new Set for " + evt)); + // this is new + fnSet = new Set(); + } + // lazy only store 2 items - this is not the case in V1.6.0 anymore + // we need to check the first parameter is string or not + if (args.length > 2) { + if (Array.isArray(args[0])) { // lazy store + // check if this type of this event already register in the lazy store + var t = args[2]; + if (!this.checkTypeInLazyStore(evt, t)) { + fnSet.add(args); + } + } else { + if (!this.checkContentExist(args, fnSet)) { + this.logger('(addToStore)', "insert new", args); + fnSet.add(args); + } } + } else { // add straight to lazy store + fnSet.add(args); } - } else { // add straight to lazy store - fnSet.add(args); - } - store.set(evt, fnSet); - return [store, fnSet.size] - }; + store.set(evt, fnSet); + return [store, fnSet.size] + }; - /** - * @param {array} args for compare - * @param {object} fnSet A Set to search from - * @return {boolean} true on exist - */ - EventService.prototype.checkContentExist = function checkContentExist (args, fnSet) { - var list = Array.from(fnSet); - return !!list.filter(function (l) { - var hash = l[0]; - if (hash === args[0]) { + /** + * @param {array} args for compare + * @param {object} fnSet A Set to search from + * @return {boolean} true on exist + */ + NbEventServiceBase.prototype.checkContentExist = function checkContentExist (args, fnSet) { + var list = Array.from(fnSet); + return !!list.filter(function (l) { + var hash = l[0]; + if (hash === args[0]) { + return true; + } + return false; + }).length; + }; + + /** + * get the existing type to make sure no mix type add to the same store + * @param {string} evtName event name + * @param {string} type the type to check + * @return {boolean} true you can add, false then you can't add this type + */ + NbEventServiceBase.prototype.checkTypeInStore = function checkTypeInStore (evtName, type) { + this.validateEvt(evtName, type); + var all = this.$get(evtName, true); + if (all === false) { + // pristine it means you can add return true; } + // it should only have ONE type in ONE event store + return !all.filter(function (list) { + var t = list[3]; + return type !== t; + }).length; + }; + + /** + * This is checking just the lazy store because the structure is different + * therefore we need to use a new method to check it + */ + NbEventServiceBase.prototype.checkTypeInLazyStore = function checkTypeInLazyStore (evtName, type) { + this.validateEvt(evtName, type); + var store = this.lazyStore.get(evtName); + this.logger('(checkTypeInLazyStore)', store); + if (store) { + return !!Array + .from(store) + .filter(function (l) { + var t = l[2]; + return t !== type; + }).length + } return false; - }).length; - }; + }; - /** - * get the existing type to make sure no mix type add to the same store - * @param {string} evtName event name - * @param {string} type the type to check - * @return {boolean} true you can add, false then you can't add this type - */ - EventService.prototype.checkTypeInStore = function checkTypeInStore (evtName, type) { - this.validateEvt(evtName); - this.validateEvt(type); - var all = this.$get(evtName, true); - if (all === false) { - // pristine it means you can add - return true; - } - // it should only have ONE type in ONE event store - return !all.filter(function (list) { - var t = list[3]; - return type !== t; - }).length; - }; + /** + * wrapper to re-use the addToStore, + * V1.3.0 add extra check to see if this type can add to this evt + * @param {string} evt event name + * @param {string} type on or once + * @param {function} callback function + * @param {object} context the context the function execute in or null + * @return {number} size of the store + */ + NbEventServiceBase.prototype.addToNormalStore = function addToNormalStore (evt, type, callback, context) { + if ( context === void 0 ) context = null; - /** - * This is checking just the lazy store because the structure is different - * therefore we need to use a new method to check it - */ - EventService.prototype.checkTypeInLazyStore = function checkTypeInLazyStore (evtName, type) { - this.validateEvt(evtName); - this.validateEvt(type); - var store = this.lazyStore.get(evtName); - this.logger('checkTypeInLazyStore', store); - if (store) { - return !!Array - .from(store) - .filter(function (l) { - var t = l[2]; - return t !== type; - }).length - } - return false; - }; + this.logger('(addToNormalStore)', evt, type, 'try to add to normal store'); + // @TODO we need to check the existing store for the type first! + if (this.checkTypeInStore(evt, type)) { + this.logger('(addToNormalStore)', (type + " can add to " + evt + " normal store")); + var key = this.hashFnToKey(callback); + var args = [this.normalStore, evt, key, callback, context, type]; + var ref = Reflect.apply(this.addToStore, this, args); + var _store = ref[0]; + var size = ref[1]; + this.normalStore = _store; + return size; + } + return false; + }; - /** - * wrapper to re-use the addToStore, - * V1.3.0 add extra check to see if this type can add to this evt - * @param {string} evt event name - * @param {string} type on or once - * @param {function} callback function - * @param {object} context the context the function execute in or null - * @return {number} size of the store - */ - EventService.prototype.addToNormalStore = function addToNormalStore (evt, type, callback, context) { + /** + * Add to lazy store this get calls when the callback is not register yet + * so we only get a payload object or even nothing + * @param {string} evt event name + * @param {array} payload of arguments or empty if there is none + * @param {object} [context=null] the context the callback execute in + * @param {string} [type=false] register a type so no other type can add to this evt + * @return {number} size of the store + */ + NbEventServiceBase.prototype.addToLazyStore = function addToLazyStore (evt, payload, context, type) { + if ( payload === void 0 ) payload = []; if ( context === void 0 ) context = null; + if ( type === void 0 ) type = false; - this.logger('addToNormalStore', evt, type, 'add to normal store'); - // @TODO we need to check the existing store for the type first! - if (this.checkTypeInStore(evt, type)) { - this.logger((type + " can add to " + evt + " store")); - var key = this.hashFnToKey(callback); - var args = [this.normalStore, evt, key, callback, context, type]; + // this is add in V1.6.0 + // when there is type then we will need to check if this already added in lazy store + // and no other type can add to this lazy store + var args = [this.lazyStore, evt, this.toArray(payload), context]; + if (type) { + args.push(type); + } var ref = Reflect.apply(this.addToStore, this, args); - var _store = ref[0]; - var size = ref[1]; - this.normalStore = _store; + var _store = ref[0]; + var size = ref[1]; + this.lazyStore = _store; return size; + }; + + /** + * make sure we store the argument correctly + * @param {*} arg could be array + * @return {array} make sured + */ + NbEventServiceBase.prototype.toArray = function toArray (arg) { + return Array.isArray(arg) ? arg : [arg]; + }; + + /** + * setter to store the Set in private + * @param {object} obj a Set + */ + prototypeAccessors.normalStore.set = function (obj) { + NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj); + }; + + /** + * @return {object} Set object + */ + prototypeAccessors.normalStore.get = function () { + return NB_EVENT_SERVICE_PRIVATE_STORE.get(this) + }; + + /** + * setter to store the Set in lazy store + * @param {object} obj a Set + */ + prototypeAccessors.lazyStore.set = function (obj) { + NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj); + }; + + /** + * @return {object} the lazy store Set + */ + prototypeAccessors.lazyStore.get = function () { + return NB_EVENT_SERVICE_PRIVATE_LAZY.get(this) + }; + + /** + * generate a hashKey to identify the function call + * The build-in store some how could store the same values! + * @param {function} fn the converted to string function + * @return {string} hashKey + */ + NbEventServiceBase.prototype.hashFnToKey = function hashFnToKey (fn) { + return hashCode(fn.toString()) + ''; + }; + + Object.defineProperties( NbEventServiceBase.prototype, prototypeAccessors ); + + return NbEventServiceBase; + }(SuspendClass)); + + // The top level + // export + var EventService = /*@__PURE__*/(function (NbStoreService) { + function EventService(config) { + if ( config === void 0 ) config = {}; + + NbStoreService.call(this, config); } - return false; - }; - /** - * Add to lazy store this get calls when the callback is not register yet - * so we only get a payload object or even nothing - * @param {string} evt event name - * @param {array} payload of arguments or empty if there is none - * @param {object} [context=null] the context the callback execute in - * @param {string} [type=false] register a type so no other type can add to this evt - * @return {number} size of the store - */ - EventService.prototype.addToLazyStore = function addToLazyStore (evt, payload, context, type) { + if ( NbStoreService ) EventService.__proto__ = NbStoreService; + EventService.prototype = Object.create( NbStoreService && NbStoreService.prototype ); + EventService.prototype.constructor = EventService; + + var prototypeAccessors = { $done: { configurable: true } }; + + /** + * logger function for overwrite + */ + EventService.prototype.logger = function logger () {}; + + ////////////////////////// + // PUBLIC METHODS // + ////////////////////////// + + /** + * Register your evt handler, note we don't check the type here, + * we expect you to be sensible and know what you are doing. + * @param {string} evt name of event + * @param {function} callback bind method --> if it's array or not + * @param {object} [context=null] to execute this call in + * @return {number} the size of the store + */ + EventService.prototype.$on = function $on (evt , callback , context) { + var this$1 = this; + if ( context === void 0 ) context = null; + + var type = 'on'; + this.validate(evt, callback); + // first need to check if this evt is in lazy store + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register first then call later + if (lazyStoreContent === false) { + this.logger('($on)', (evt + " callback is not in lazy store")); + // @TODO we need to check if there was other listener to this + // event and are they the same type then we could solve that + // register the different type to the same event name + + return this.addToNormalStore(evt, type, callback, context) + } + this.logger('($on)', (evt + " found in lazy store")); + // this is when they call $trigger before register this callback + var size = 0; + lazyStoreContent.forEach(function (content) { + var payload = content[0]; + var ctx = content[1]; + var t = content[2]; + if (t && t !== type) { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this$1.run(callback, payload, context || ctx); + size += this$1.addToNormalStore(evt, type, callback, context || ctx); + }); + return size; + }; + + /** + * once only registered it once, there is no overwrite option here + * @NOTE change in v1.3.0 $once can add multiple listeners + * but once the event fired, it will remove this event (see $only) + * @param {string} evt name + * @param {function} callback to execute + * @param {object} [context=null] the handler execute in + * @return {boolean} result + */ + EventService.prototype.$once = function $once (evt , callback , context) { + if ( context === void 0 ) context = null; + + this.validate(evt, callback); + var type = 'once'; + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register before call $trigger + var nStore = this.normalStore; + if (lazyStoreContent === false) { + this.logger('($once)', (evt + " not in the lazy store")); + // v1.3.0 $once now allow to add multiple listeners + return this.addToNormalStore(evt, type, callback, context) + } else { + // now this is the tricky bit + // there is a potential bug here that cause by the developer + // if they call $trigger first, the lazy won't know it's a once call + // so if in the middle they register any call with the same evt name + // then this $once call will be fucked - add this to the documentation + this.logger('($once)', lazyStoreContent); + var list = Array.from(lazyStoreContent); + // should never have more than 1 + var ref = list[0]; + var payload = ref[0]; + var ctx = ref[1]; + var t = ref[2]; + if (t && t !== type) { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this.run(callback, payload, context || ctx); + // remove this evt from store + this.$off(evt); + } + }; + + /** + * This one event can only bind one callbackback + * @param {string} evt event name + * @param {function} callback event handler + * @param {object} [context=null] the context the event handler execute in + * @return {boolean} true bind for first time, false already existed + */ + EventService.prototype.$only = function $only (evt, callback, context) { + var this$1 = this; + if ( context === void 0 ) context = null; + + this.validate(evt, callback); + var type = 'only'; + var added = false; + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register before call $trigger + var nStore = this.normalStore; + if (!nStore.has(evt)) { + this.logger("($only)", (evt + " add to store")); + added = this.addToNormalStore(evt, type, callback, context); + } + if (lazyStoreContent !== false) { + // there are data store in lazy store + this.logger('($only)', (evt + " found data in lazy store to execute")); + var list = Array.from(lazyStoreContent); + // $only allow to trigger this multiple time on the single handler + list.forEach( function (l) { + var payload = l[0]; + var ctx = l[1]; + var t = l[2]; + if (t && t !== type) { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this$1.run(callback, payload, context || ctx); + }); + } + return added; + }; + + /** + * $only + $once this is because I found a very subtile bug when we pass a + * resolver, rejecter - and it never fire because that's OLD adeed in v1.4.0 + * @param {string} evt event name + * @param {function} callback to call later + * @param {object} [context=null] exeucte context + * @return {void} + */ + EventService.prototype.$onlyOnce = function $onlyOnce (evt, callback, context) { + if ( context === void 0 ) context = null; + + this.validate(evt, callback); + var type = 'onlyOnce'; + var added = false; + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register before call $trigger + var nStore = this.normalStore; + if (!nStore.has(evt)) { + this.logger("($onlyOnce)", (evt + " add to store")); + added = this.addToNormalStore(evt, type, callback, context); + } + if (lazyStoreContent !== false) { + // there are data store in lazy store + this.logger('($onlyOnce)', lazyStoreContent); + var list = Array.from(lazyStoreContent); + // should never have more than 1 + var ref = list[0]; + var payload = ref[0]; + var ctx = ref[1]; + var t = ref[2]; + if (t && t !== 'onlyOnce') { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this.run(callback, payload, context || ctx); + // remove this evt from store + this.$off(evt); + } + return added; + }; + + /** + * This is a shorthand of $off + $on added in V1.5.0 + * @param {string} evt event name + * @param {function} callback to exeucte + * @param {object} [context = null] or pass a string as type + * @param {string} [type=on] what type of method to replace + * @return {} + */ + EventService.prototype.$replace = function $replace (evt, callback, context, type) { + if ( context === void 0 ) context = null; + if ( type === void 0 ) type = 'on'; + + if (this.validateType(type)) { + this.$off(evt); + var method = this['$' + type]; + return Reflect.apply(method, this, [evt, callback, context]) + } + throw new Error((type + " is not supported!")) + }; + + /** + * trigger the event + * @param {string} evt name NOT allow array anymore! + * @param {mixed} [payload = []] pass to fn + * @param {object|string} [context = null] overwrite what stored + * @param {string} [type=false] if pass this then we need to add type to store too + * @return {number} if it has been execute how many times + */ + EventService.prototype.$trigger = function $trigger (evt , payload , context, type) { if ( payload === void 0 ) payload = []; if ( context === void 0 ) context = null; if ( type === void 0 ) type = false; - // this is add in V1.6.0 - // when there is type then we will need to check if this already added in lazy store - // and no other type can add to this lazy store - var args = [this.lazyStore, evt, this.toArray(payload), context]; - if (type) { - args.push(type); - } - var ref = Reflect.apply(this.addToStore, this, args); - var _store = ref[0]; - var size = ref[1]; - this.lazyStore = _store; - return size; - }; + this.validateEvt(evt); + var found = 0; + // first check the normal store + var nStore = this.normalStore; + this.logger('($trigger)', 'normalStore', nStore); + if (nStore.has(evt)) { + // @1.8.0 to add the suspend queue + var added = this.$queue(evt, payload, context, type); + this.logger('($trigger)', evt, 'found; add to queue: ', added); + if (added === true) { + return false; // not executed + } + var nSet = Array.from(nStore.get(evt)); + var ctn = nSet.length; + var hasOnce = false; + for (var i=0; i < ctn; ++i) { + ++found; + // this.logger('found', found) + var ref = nSet[i]; + var _ = ref[0]; + var callback = ref[1]; + var ctx = ref[2]; + var type$1 = ref[3]; + this.run(callback, payload, context || ctx); + if (type$1 === 'once' || type$1 === 'onlyOnce') { + hasOnce = true; + } + } + if (hasOnce) { + nStore.delete(evt); + } + return found; + } + // now this is not register yet + this.addToLazyStore(evt, payload, context, type); + return found; + }; - /** - * make sure we store the argument correctly - * @param {*} arg could be array - * @return {array} make sured - */ - EventService.prototype.toArray = function toArray (arg) { - return Array.isArray(arg) ? arg : [arg]; - }; + /** + * this is an alias to the $trigger + * @NOTE breaking change in V1.6.0 we swap the parameter around + * @param {string} evt event name + * @param {*} params pass to the callback + * @param {string} type of call + * @param {object} context what context callback execute in + * @return {*} from $trigger + */ + EventService.prototype.$call = function $call (evt, params, type, context) { + if ( type === void 0 ) type = false; + if ( context === void 0 ) context = null; - /** - * setter to store the Set in private - * @param {object} obj a Set - */ - prototypeAccessors.normalStore.set = function (obj) { - NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj); - }; + var args = [evt, params]; + args.push(context, type); + return Reflect.apply(this.$trigger, this, args) + }; - /** - * @return {object} Set object - */ - prototypeAccessors.normalStore.get = function () { - return NB_EVENT_SERVICE_PRIVATE_STORE.get(this) - }; + /** + * remove the evt from all the stores + * @param {string} evt name + * @return {boolean} true actually delete something + */ + EventService.prototype.$off = function $off (evt) { + this.validateEvt(evt); + var stores = [ this.lazyStore, this.normalStore ]; + var found = false; + stores.forEach(function (store) { + if (store.has(evt)) { + found = true; + store.delete(evt); + } + }); + return found; + }; - /** - * setter to store the Set in lazy store - * @param {object} obj a Set - */ - prototypeAccessors.lazyStore.set = function (obj) { - NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj); - }; + /** + * return all the listener from the event + * @param {string} evtName event name + * @param {boolean} [full=false] if true then return the entire content + * @return {array|boolean} listerner(s) or false when not found + */ + EventService.prototype.$get = function $get (evt, full) { + if ( full === void 0 ) full = false; - /** - * @return {object} the lazy store Set - */ - prototypeAccessors.lazyStore.get = function () { - return NB_EVENT_SERVICE_PRIVATE_LAZY.get(this) - }; + this.validateEvt(evt); + var store = this.normalStore; + if (store.has(evt)) { + return Array + .from(store.get(evt)) + .map( function (l) { + if (full) { + return l; + } + var key = l[0]; + var callback = l[1]; + return callback; + }) + } + return false; + }; - /** - * generate a hashKey to identify the function call - * The build-in store some how could store the same values! - * @param {function} fn the converted to string function - * @return {string} hashKey - */ - EventService.prototype.hashFnToKey = function hashFnToKey (fn) { - return hashCode(fn.toString()) + ''; - }; + /** + * store the return result from the run + * @param {*} value whatever return from callback + */ + prototypeAccessors.$done.set = function (value) { + this.logger('($done)', 'value: ', value); + if (this.keep) { + this.result.push(value); + } else { + this.result = value; + } + }; + + /** + * @TODO is there any real use with the keep prop? + * getter for $done + * @return {*} whatever last store result + */ + prototypeAccessors.$done.get = function () { + if (this.keep) { + this.logger('(get $done)', this.result); + return this.result[this.result.length - 1] + } + return this.result; + }; + + Object.defineProperties( EventService.prototype, prototypeAccessors ); - Object.defineProperties( EventService.prototype, prototypeAccessors ); + return EventService; + }(NbEventServiceBase)); // default diff --git a/packages/ws-client/dist/jsonql-ws-client.js.map b/packages/ws-client/dist/jsonql-ws-client.js.map index 7141982b..12a7d8d7 100644 --- a/packages/ws-client/dist/jsonql-ws-client.js.map +++ b/packages/ws-client/dist/jsonql-ws-client.js.map @@ -1 +1 @@ -{"version":3,"file":"jsonql-ws-client.js","sources":["../node_modules/jsonql-jwt/src/client/socketio/socket-io-client.js","../node_modules/jsonql-jwt/src/client/socketio/handshake-login.js","../node_modules/jsonql-errors/src/500-error.js","../node_modules/jsonql-errors/src/enum-error.js","../node_modules/jsonql-errors/src/type-error.js","../node_modules/jsonql-errors/src/checker-error.js","../node_modules/jsonql-errors/src/validation-error.js","../node_modules/jsonql-errors/src/server-error.js","../node_modules/jsonql-jwt/src/client/socketio/roundtrip-login.js","../node_modules/rollup-plugin-node-globals/src/global.js","../node_modules/lodash-es/_objectToString.js","../node_modules/lodash-es/isObjectLike.js","../node_modules/lodash-es/_arrayMap.js","../node_modules/lodash-es/isArray.js","../node_modules/lodash-es/isObject.js","../node_modules/lodash-es/identity.js","../node_modules/lodash-es/_toSource.js","../node_modules/lodash-es/_getValue.js","../node_modules/lodash-es/_apply.js","../node_modules/lodash-es/_copyArray.js","../node_modules/lodash-es/_shortOut.js","../node_modules/lodash-es/constant.js","../node_modules/lodash-es/_baseFindIndex.js","../node_modules/lodash-es/_baseIsNaN.js","../node_modules/lodash-es/_strictIndexOf.js","../node_modules/lodash-es/_isIndex.js","../node_modules/lodash-es/eq.js","../node_modules/lodash-es/isLength.js","../node_modules/lodash-es/_isPrototype.js","../node_modules/lodash-es/_baseTimes.js","../node_modules/lodash-es/stubFalse.js","../node_modules/lodash-es/_baseUnary.js","../node_modules/lodash-es/_overArg.js","../node_modules/lodash-es/_nativeKeysIn.js","../node_modules/lodash-es/_hashDelete.js","../node_modules/lodash-es/_listCacheClear.js","../node_modules/lodash-es/_isKeyable.js","../node_modules/lodash-es/_arrayPush.js","../node_modules/lodash-es/_baseSlice.js","../node_modules/lodash-es/_hasUnicode.js","../node_modules/lodash-es/_asciiToArray.js","../node_modules/lodash-es/_unicodeToArray.js","../node_modules/lodash-es/_stackDelete.js","../node_modules/lodash-es/_stackGet.js","../node_modules/lodash-es/_stackHas.js","../node_modules/lodash-es/_arrayFilter.js","../node_modules/lodash-es/stubArray.js","../node_modules/lodash-es/_setCacheAdd.js","../node_modules/lodash-es/_setCacheHas.js","../node_modules/lodash-es/_arraySome.js","../node_modules/lodash-es/_cacheHas.js","../node_modules/lodash-es/_mapToArray.js","../node_modules/lodash-es/_setToArray.js","../node_modules/lodash-es/_matchesStrictComparable.js","../node_modules/lodash-es/_baseHasIn.js","../node_modules/lodash-es/_baseProperty.js","../node_modules/lodash-es/_createBaseFor.js","../node_modules/lodash-es/_safeGet.js","../node_modules/lodash-es/_baseFindKey.js","../node_modules/lodash-es/isNull.js","../node_modules/lodash-es/isUndefined.js","../node_modules/lodash-es/negate.js","../node_modules/jsonql-params-validator/src/not-empty.js","../node_modules/jsonql-params-validator/src/number.js","../node_modules/jsonql-params-validator/src/string.js","../node_modules/jsonql-params-validator/src/boolean.js","../node_modules/jsonql-params-validator/src/any.js","../node_modules/jsonql-params-validator/src/constants.js","../node_modules/jsonql-params-validator/src/combine.js","../node_modules/jsonql-params-validator/src/array.js","../node_modules/jsonql-params-validator/src/object.js","../node_modules/jsonql-params-validator/src/validator.js","../node_modules/jsonql-params-validator/src/is-in-array.js","../node_modules/jsonql-params-validator/src/options/run-validation.js","../node_modules/jsonql-params-validator/src/options/check-options-async.js","../node_modules/jsonql-params-validator/src/options/construct-config.js","../node_modules/jsonql-params-validator/src/options/index.js","../node_modules/jsonql-params-validator/src/check-is-contract.js","../node_modules/jsonql-params-validator/src/params-api.js","../node_modules/jsonql-params-validator/index.js","../node_modules/jsonql-jwt/src/client/utils/group-by-namespace.js","../node_modules/jsonql-jwt/src/client/utils/chain-promises.js","../node_modules/jwt-decode/lib/atob.js","../node_modules/jsonql-jwt/src/client/ws/ws.js","../src/utils/constants.js","../src/utils/client-generator.js","../src/utils/create-nsp-client.js","../node_modules/nb-event-service/src/hash-code.js","../node_modules/nb-event-service/src/event-service.js","../node_modules/nb-event-service/index.js","../src/utils/process-contract.js","../src/utils/index.js","../src/client-event-handler.js","../src/ws/extract-ws-payload.js","../src/ws/ws-main-handler.js","../src/ws/create-client.js","../src/ws/index.js","../src/io/create-client.js","../src/generator.js","../src/main.js","../index.js"],"sourcesContent":["// this should work on browser as well as node\n// import io from 'socket.io-cilent'\n\n/**\n * Create a normal client\n * @param {object} io socket io instance\n * @param {string} url end point\n * @param {object} [options={}] configuration\n * @return {object} nsp instance\n */\nexport default function socketIoClient(io, url, options = {}) {\n return io.connect(url, options)\n}\n","// handshake login\nimport { TOKEN_PARAM_NAME, DEFAULT_WS_WAIT_TIME } from 'jsonql-constants';\nimport socketIoClient from './socket-io-client'\n\n/**\n * Create a async version to match up the rest of the api\n * @param {object} io socket io instance\n * @param {string} url end point\n * @param {object} [options={}] configuration\n * @return {object} Promise resolve to nsp instance\n */\nexport function socketIoClientAsync(...args) {\n return Promise.resolve(\n Reflect.apply(socketIoClient, null, args)\n )\n}\n\n/**\n * Login during handshake\n * @param {object} io the new socket.io instance\n * @param {string} token to send\n * @param {object} [options = {}] extra options\n * @return {object} the io object itself\n */\nexport function socketIoHandshakeLogin(io, url, token, options = {}) {\n const wait = options.timeout || DEFAULT_WS_WAIT_TIME;\n const config = Object.assign({}, options, {\n query: [TOKEN_PARAM_NAME, token].join('=')\n })\n let timer;\n const nsp = socketIoClient(io, url, config)\n return new Promise((resolver, rejecter) => {\n timer = setTimeout(() => {\n rejecter()\n }, wait)\n nsp.on('connect', () => {\n console.info('socketIoHandshakeLogin connected')\n resolver(nsp)\n clearTimeout(timer)\n })\n })\n}\n","/**\n * This is a custom error to throw when server throw a 500\n * This help us to capture the right error, due to the call happens in sequence\n * @param {string} message to tell what happen\n * @param {mixed} extra things we want to add, 500?\n */\nexport default class Jsonql500Error extends Error {\n constructor(...args) {\n super(...args);\n\n this.message = args[0];\n this.detail = args[1];\n\n this.className = Jsonql500Error.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, Jsonql500Error);\n }\n }\n\n static get statusCode() {\n return 500;\n }\n\n static get name() {\n return 'Jsonql500Error';\n }\n\n}\n","// this get throw from within the checkOptions when run through the enum failed\nexport default class JsonqlEnumError extends Error {\n constructor(...args) {\n super(...args);\n \n this.message = args[0];\n this.detail = args[1];\n\n this.className = JsonqlEnumError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlEnumError);\n }\n }\n\n static get name() {\n return 'JsonqlEnumError';\n }\n}\n","// this will throw from inside the checkOptions\nexport default class JsonqlTypeError extends Error {\n constructor(...args) {\n super(...args);\n\n this.message = args[0];\n this.detail = args[1];\n\n this.className = JsonqlTypeError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlTypeError);\n }\n }\n\n static get name() {\n return 'JsonqlTypeError';\n }\n}\n","// allow supply a custom checker function\n// if that failed then we throw this error\nexport default class JsonqlCheckerError extends Error {\n constructor(...args) {\n super(...args);\n this.message = args[0];\n this.detail = args[1];\n\n this.className = JsonqlCheckerError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlCheckerError);\n }\n }\n\n static get name() {\n return 'JsonqlCheckerError';\n }\n}\n","// custom validation error class\n// when validaton failed\nexport default class JsonqlValidationError extends Error {\n constructor(...args) {\n super(...args);\n\n this.message = args[0];\n this.detail = args[1];\n\n this.className = JsonqlValidationError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlValidationError);\n }\n }\n\n static get name() {\n return 'JsonqlValidationError';\n }\n}\n","// this is from an example from Koa team to use for internal middleware ctx.throw\n// but after the test the res.body part is unable to extract the required data\n// I keep this one here for future reference\n\nexport default class JsonqlServerError extends Error {\n\n constructor(statusCode, message) {\n super(message);\n this.statusCode = statusCode;\n this.className = JsonqlServerError.name;\n }\n\n static get name() {\n return 'JsonqlServerError';\n }\n}\n","// import { isString } from 'jsonql-params-validator';\nimport { JsonqlValidationError } from 'jsonql-errors';\nimport socketIoClient from './socket-io-client'\n/**\n * The core method of the socketJwt client side\n * @param {object} socket the socket.io connected instance\n * @param {string} token for validation\n * @param {function} onAuthenitcated callback when authenticated\n * @param {function} onUnauthorized callback when authorized\n * @return {void}\n */\nconst socketIoLoginAction = (socket, token, onAuthenticated, onUnauthorized) => {\n socket\n .emit('authenticate', { token })\n .on('authenticated', onAuthenticated)\n .on('unauthorized', onUnauthorized)\n}\n\n/**\n * completely rethink about how the browser version should be!\n *\n */\nexport default function socketIoRoundtripLogin(io, url, token, options = {}) {\n const socket = socketIoClient(io, url)\n return new Promise((resolver, rejecter) => {\n socketIoLoginAction(socket, token, () => resolver(socket) , rejecter);\n })\n}\n","export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nexport default isObject;\n","/**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\nfunction identity(value) {\n return value;\n}\n\nexport default identity;\n","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n}\n\nexport default toSource;\n","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n return object == null ? undefined : object[key];\n}\n\nexport default getValue;\n","/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\nexport default apply;\n","/**\n * Copies the values of `source` to `array`.\n *\n * @private\n * @param {Array} source The array to copy values from.\n * @param {Array} [array=[]] The array to copy values to.\n * @returns {Array} Returns `array`.\n */\nfunction copyArray(source, array) {\n var index = -1,\n length = source.length;\n\n array || (array = Array(length));\n while (++index < length) {\n array[index] = source[index];\n }\n return array;\n}\n\nexport default copyArray;\n","/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n}\n\nexport default shortOut;\n","/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n return function() {\n return value;\n };\n}\n\nexport default constant;\n","/**\n * The base implementation of `_.findIndex` and `_.findLastIndex` without\n * support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} predicate The function invoked per iteration.\n * @param {number} fromIndex The index to search from.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseFindIndex(array, predicate, fromIndex, fromRight) {\n var length = array.length,\n index = fromIndex + (fromRight ? 1 : -1);\n\n while ((fromRight ? index-- : ++index < length)) {\n if (predicate(array[index], index, array)) {\n return index;\n }\n }\n return -1;\n}\n\nexport default baseFindIndex;\n","/**\n * The base implementation of `_.isNaN` without support for number objects.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.\n */\nfunction baseIsNaN(value) {\n return value !== value;\n}\n\nexport default baseIsNaN;\n","/**\n * A specialized version of `_.indexOf` which performs strict equality\n * comparisons of values, i.e. `===`.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction strictIndexOf(array, value, fromIndex) {\n var index = fromIndex - 1,\n length = array.length;\n\n while (++index < length) {\n if (array[index] === value) {\n return index;\n }\n }\n return -1;\n}\n\nexport default strictIndexOf;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n var type = typeof value;\n length = length == null ? MAX_SAFE_INTEGER : length;\n\n return !!length &&\n (type == 'number' ||\n (type != 'symbol' && reIsUint.test(value))) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\nexport default isIndex;\n","/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n return value === other || (value !== value && other !== other);\n}\n\nexport default eq;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\nexport default isLength;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n}\n\nexport default isPrototype;\n","/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\nexport default baseTimes;\n","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n return false;\n}\n\nexport default stubFalse;\n","/**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\nfunction baseUnary(func) {\n return function(value) {\n return func(value);\n };\n}\n\nexport default baseUnary;\n","/**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\nfunction overArg(func, transform) {\n return function(arg) {\n return func(transform(arg));\n };\n}\n\nexport default overArg;\n","/**\n * This function is like\n * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * except that it includes inherited enumerable properties.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction nativeKeysIn(object) {\n var result = [];\n if (object != null) {\n for (var key in Object(object)) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default nativeKeysIn;\n","/**\n * Removes `key` and its value from the hash.\n *\n * @private\n * @name delete\n * @memberOf Hash\n * @param {Object} hash The hash to modify.\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction hashDelete(key) {\n var result = this.has(key) && delete this.__data__[key];\n this.size -= result ? 1 : 0;\n return result;\n}\n\nexport default hashDelete;\n","/**\n * Removes all key-value entries from the list cache.\n *\n * @private\n * @name clear\n * @memberOf ListCache\n */\nfunction listCacheClear() {\n this.__data__ = [];\n this.size = 0;\n}\n\nexport default listCacheClear;\n","/**\n * Checks if `value` is suitable for use as unique object key.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n */\nfunction isKeyable(value) {\n var type = typeof value;\n return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n ? (value !== '__proto__')\n : (value === null);\n}\n\nexport default isKeyable;\n","/**\n * Appends the elements of `values` to `array`.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to append.\n * @returns {Array} Returns `array`.\n */\nfunction arrayPush(array, values) {\n var index = -1,\n length = values.length,\n offset = array.length;\n\n while (++index < length) {\n array[offset + index] = values[index];\n }\n return array;\n}\n\nexport default arrayPush;\n","/**\n * The base implementation of `_.slice` without an iteratee call guard.\n *\n * @private\n * @param {Array} array The array to slice.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the slice of `array`.\n */\nfunction baseSlice(array, start, end) {\n var index = -1,\n length = array.length;\n\n if (start < 0) {\n start = -start > length ? 0 : (length + start);\n }\n end = end > length ? length : end;\n if (end < 0) {\n end += length;\n }\n length = start > end ? 0 : ((end - start) >>> 0);\n start >>>= 0;\n\n var result = Array(length);\n while (++index < length) {\n result[index] = array[index + start];\n }\n return result;\n}\n\nexport default baseSlice;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsVarRange = '\\\\ufe0e\\\\ufe0f';\n\n/** Used to compose unicode capture groups. */\nvar rsZWJ = '\\\\u200d';\n\n/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */\nvar reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');\n\n/**\n * Checks if `string` contains Unicode symbols.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {boolean} Returns `true` if a symbol is found, else `false`.\n */\nfunction hasUnicode(string) {\n return reHasUnicode.test(string);\n}\n\nexport default hasUnicode;\n","/**\n * Converts an ASCII `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction asciiToArray(string) {\n return string.split('');\n}\n\nexport default asciiToArray;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsVarRange = '\\\\ufe0e\\\\ufe0f';\n\n/** Used to compose unicode capture groups. */\nvar rsAstral = '[' + rsAstralRange + ']',\n rsCombo = '[' + rsComboRange + ']',\n rsFitz = '\\\\ud83c[\\\\udffb-\\\\udfff]',\n rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',\n rsNonAstral = '[^' + rsAstralRange + ']',\n rsRegional = '(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}',\n rsSurrPair = '[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]',\n rsZWJ = '\\\\u200d';\n\n/** Used to compose unicode regexes. */\nvar reOptMod = rsModifier + '?',\n rsOptVar = '[' + rsVarRange + ']?',\n rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',\n rsSeq = rsOptVar + reOptMod + rsOptJoin,\n rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';\n\n/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */\nvar reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');\n\n/**\n * Converts a Unicode `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction unicodeToArray(string) {\n return string.match(reUnicode) || [];\n}\n\nexport default unicodeToArray;\n","/**\n * Removes `key` and its value from the stack.\n *\n * @private\n * @name delete\n * @memberOf Stack\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction stackDelete(key) {\n var data = this.__data__,\n result = data['delete'](key);\n\n this.size = data.size;\n return result;\n}\n\nexport default stackDelete;\n","/**\n * Gets the stack value for `key`.\n *\n * @private\n * @name get\n * @memberOf Stack\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction stackGet(key) {\n return this.__data__.get(key);\n}\n\nexport default stackGet;\n","/**\n * Checks if a stack value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Stack\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction stackHas(key) {\n return this.__data__.has(key);\n}\n\nexport default stackHas;\n","/**\n * A specialized version of `_.filter` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\nfunction arrayFilter(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (predicate(value, index, array)) {\n result[resIndex++] = value;\n }\n }\n return result;\n}\n\nexport default arrayFilter;\n","/**\n * This method returns a new empty array.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {Array} Returns the new empty array.\n * @example\n *\n * var arrays = _.times(2, _.stubArray);\n *\n * console.log(arrays);\n * // => [[], []]\n *\n * console.log(arrays[0] === arrays[1]);\n * // => false\n */\nfunction stubArray() {\n return [];\n}\n\nexport default stubArray;\n","/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Adds `value` to the array cache.\n *\n * @private\n * @name add\n * @memberOf SetCache\n * @alias push\n * @param {*} value The value to cache.\n * @returns {Object} Returns the cache instance.\n */\nfunction setCacheAdd(value) {\n this.__data__.set(value, HASH_UNDEFINED);\n return this;\n}\n\nexport default setCacheAdd;\n","/**\n * Checks if `value` is in the array cache.\n *\n * @private\n * @name has\n * @memberOf SetCache\n * @param {*} value The value to search for.\n * @returns {number} Returns `true` if `value` is found, else `false`.\n */\nfunction setCacheHas(value) {\n return this.__data__.has(value);\n}\n\nexport default setCacheHas;\n","/**\n * A specialized version of `_.some` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n */\nfunction arraySome(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (predicate(array[index], index, array)) {\n return true;\n }\n }\n return false;\n}\n\nexport default arraySome;\n","/**\n * Checks if a `cache` value for `key` exists.\n *\n * @private\n * @param {Object} cache The cache to query.\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction cacheHas(cache, key) {\n return cache.has(key);\n}\n\nexport default cacheHas;\n","/**\n * Converts `map` to its key-value pairs.\n *\n * @private\n * @param {Object} map The map to convert.\n * @returns {Array} Returns the key-value pairs.\n */\nfunction mapToArray(map) {\n var index = -1,\n result = Array(map.size);\n\n map.forEach(function(value, key) {\n result[++index] = [key, value];\n });\n return result;\n}\n\nexport default mapToArray;\n","/**\n * Converts `set` to an array of its values.\n *\n * @private\n * @param {Object} set The set to convert.\n * @returns {Array} Returns the values.\n */\nfunction setToArray(set) {\n var index = -1,\n result = Array(set.size);\n\n set.forEach(function(value) {\n result[++index] = value;\n });\n return result;\n}\n\nexport default setToArray;\n","/**\n * A specialized version of `matchesProperty` for source values suitable\n * for strict equality comparisons, i.e. `===`.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @param {*} srcValue The value to match.\n * @returns {Function} Returns the new spec function.\n */\nfunction matchesStrictComparable(key, srcValue) {\n return function(object) {\n if (object == null) {\n return false;\n }\n return object[key] === srcValue &&\n (srcValue !== undefined || (key in Object(object)));\n };\n}\n\nexport default matchesStrictComparable;\n","/**\n * The base implementation of `_.hasIn` without support for deep paths.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {Array|string} key The key to check.\n * @returns {boolean} Returns `true` if `key` exists, else `false`.\n */\nfunction baseHasIn(object, key) {\n return object != null && key in Object(object);\n}\n\nexport default baseHasIn;\n","/**\n * The base implementation of `_.property` without support for deep paths.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @returns {Function} Returns the new accessor function.\n */\nfunction baseProperty(key) {\n return function(object) {\n return object == null ? undefined : object[key];\n };\n}\n\nexport default baseProperty;\n","/**\n * Creates a base function for methods like `_.forIn` and `_.forOwn`.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\nfunction createBaseFor(fromRight) {\n return function(object, iteratee, keysFunc) {\n var index = -1,\n iterable = Object(object),\n props = keysFunc(object),\n length = props.length;\n\n while (length--) {\n var key = props[fromRight ? length : ++index];\n if (iteratee(iterable[key], key, iterable) === false) {\n break;\n }\n }\n return object;\n };\n}\n\nexport default createBaseFor;\n","/**\n * Gets the value at `key`, unless `key` is \"__proto__\".\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction safeGet(object, key) {\n if (key == '__proto__') {\n return;\n }\n\n return object[key];\n}\n\nexport default safeGet;\n","/**\n * The base implementation of methods like `_.findKey` and `_.findLastKey`,\n * without support for iteratee shorthands, which iterates over `collection`\n * using `eachFunc`.\n *\n * @private\n * @param {Array|Object} collection The collection to inspect.\n * @param {Function} predicate The function invoked per iteration.\n * @param {Function} eachFunc The function to iterate over `collection`.\n * @returns {*} Returns the found element or its key, else `undefined`.\n */\nfunction baseFindKey(collection, predicate, eachFunc) {\n var result;\n eachFunc(collection, function(value, key, collection) {\n if (predicate(value, key, collection)) {\n result = key;\n return false;\n }\n });\n return result;\n}\n\nexport default baseFindKey;\n","/**\n * Checks if `value` is `null`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `null`, else `false`.\n * @example\n *\n * _.isNull(null);\n * // => true\n *\n * _.isNull(void 0);\n * // => false\n */\nfunction isNull(value) {\n return value === null;\n}\n\nexport default isNull;\n","/**\n * Checks if `value` is `undefined`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.\n * @example\n *\n * _.isUndefined(void 0);\n * // => true\n *\n * _.isUndefined(null);\n * // => false\n */\nfunction isUndefined(value) {\n return value === undefined;\n}\n\nexport default isUndefined;\n","/** Error message constants. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/**\n * Creates a function that negates the result of the predicate `func`. The\n * `func` predicate is invoked with the `this` binding and arguments of the\n * created function.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Function\n * @param {Function} predicate The predicate to negate.\n * @returns {Function} Returns the new negated function.\n * @example\n *\n * function isEven(n) {\n * return n % 2 == 0;\n * }\n *\n * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));\n * // => [1, 3, 5]\n */\nfunction negate(predicate) {\n if (typeof predicate != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n return function() {\n var args = arguments;\n switch (args.length) {\n case 0: return !predicate.call(this);\n case 1: return !predicate.call(this, args[0]);\n case 2: return !predicate.call(this, args[0], args[1]);\n case 3: return !predicate.call(this, args[0], args[1], args[2]);\n }\n return !predicate.apply(this, args);\n };\n}\n\nexport default negate;\n","/**\n * Check several parameter that there is something in the param\n * @param {*} param input\n * @return {boolean}\n */\nimport { trim, isArray } from 'lodash-es'\n\nexport default a => {\n if (isArray(a)) {\n return true;\n }\n return a !== undefined && a !== null && trim(a) !== '';\n}\n","// validator numbers\n// import { NUMBER_TYPES } from './constants';\nimport { isNaN, isString } from 'lodash-es'\n/**\n * @2015-05-04 found a problem if the value is a number like string\n * it will pass, so add a check if it's string before we pass to next\n * @param {number} value expected value\n * @return {boolean} true if OK\n */\nconst checkIsNumber = function(value) {\n return isString(value) ? false : !isNaN( parseFloat(value) )\n}\n\nexport default checkIsNumber\n","// validate string type\nimport { isString, trim } from 'lodash-es'\n/**\n * @param {string} value expected value\n * @return {boolean} true if OK\n */\nconst checkIsString = function(value) {\n return (trim(value) !== '') ? isString(value) : false;\n}\n\nexport default checkIsString;\n","// check for boolean\nimport { isBoolean } from 'lodash-es'\n/**\n * @param {boolean} value expected\n * @return {boolean} true if OK\n */\nconst checkIsBoolean = function(value) {\n return isBoolean(value);\n};\n\nexport default checkIsBoolean\n","// validate any thing only check if there is something\nimport { isNull, trim, isUndefined } from 'lodash-es'\n/**\n * @param {*} value the value\n * @param {boolean} [checkNull=true] strict check if there is null value\n * @return {boolean} true is OK\n */\nconst checkIsAny = function(value, checkNull = true) {\n if (!isUndefined(value) && value !== '' && trim(value) !== '') {\n if (checkNull === false || (checkNull === true && !isNull(value))) {\n return true;\n }\n }\n return false;\n};\n\nexport default checkIsAny\n","// Good practice rule - No magic number\n\nexport const ARGS_NOT_ARRAY_ERR = `args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)`;\nexport const PARAMS_NOT_ARRAY_ERR = `params is not an array! Did something gone wrong when you generate the contract.json?`;\nexport const EXCEPTION_CASE_ERR = 'Could not understand your arguments and parameter structure!';\nexport const UNUSUAL_CASE_ERR = 'This is an unusual situation where the arguments are more than the params, but not mark as spread';\n\n// re-export\nimport * as JSONQL_CONSTANTS from 'jsonql-constants';\n// @TODO the jsdoc return array. and we should also allow array syntax\nexport const DEFAULT_TYPE = JSONQL_CONSTANTS.DEFAULT_TYPE;\nexport const ARRAY_TYPE_LFT = JSONQL_CONSTANTS.ARRAY_TYPE_LFT;\nexport const ARRAY_TYPE_RGT = JSONQL_CONSTANTS.ARRAY_TYPE_RGT;\n\nexport const TYPE_KEY = JSONQL_CONSTANTS.TYPE_KEY;\nexport const OPTIONAL_KEY = JSONQL_CONSTANTS.OPTIONAL_KEY;\nexport const ENUM_KEY = JSONQL_CONSTANTS.ENUM_KEY;\nexport const ARGS_KEY = JSONQL_CONSTANTS.ARGS_KEY;\nexport const CHECKER_KEY = JSONQL_CONSTANTS.CHECKER_KEY;\nexport const ALIAS_KEY = JSONQL_CONSTANTS.ALIAS_KEY;\n\nexport const ARRAY_TYPE = JSONQL_CONSTANTS.ARRAY_TYPE;\nexport const OBJECT_TYPE = JSONQL_CONSTANTS.OBJECT_TYPE;\nexport const STRING_TYPE = JSONQL_CONSTANTS.STRING_TYPE;\nexport const BOOLEAN_TYPE = JSONQL_CONSTANTS.BOOLEAN_TYPE;\nexport const NUMBER_TYPE = JSONQL_CONSTANTS.NUMBER_TYPE;\nexport const KEY_WORD = JSONQL_CONSTANTS.KEY_WORD;\nexport const OR_SEPERATOR = JSONQL_CONSTANTS.OR_SEPERATOR;\n\n// not actually in use\n// export const NUMBER_TYPES = JSONQL_CONSTANTS.NUMBER_TYPES;\n","// primitive types\nimport checkIsNumber from './number'\nimport checkIsString from './string'\nimport checkIsBoolean from './boolean'\nimport checkIsAny from './any'\nimport { NUMBER_TYPE, STRING_TYPE, BOOLEAN_TYPE } from './constants'\n\n/**\n * this is a wrapper method to call different one based on their type\n * @param {string} type to check\n * @return {function} a function to handle the type\n */\nconst combineFn = function(type) {\n switch (type) {\n case NUMBER_TYPE:\n return checkIsNumber;\n case STRING_TYPE:\n return checkIsString;\n case BOOLEAN_TYPE:\n return checkIsBoolean;\n default:\n return checkIsAny;\n }\n}\n\nexport default combineFn\n","// validate array type\nimport { isArray, trim } from 'lodash-es'\nimport combineFn from './combine'\nimport {\n ARRAY_TYPE_LFT,\n ARRAY_TYPE_RGT,\n OR_SEPERATOR\n} from './constants'\n\n/**\n * @param {array} value expected\n * @param {string} [type=''] pass the type if we encounter array. then we need to check the value as well\n * @return {boolean} true if OK\n */\nexport const checkIsArray = function(value, type='') {\n if (isArray(value)) {\n if (type === '' || trim(type)==='') {\n return true;\n }\n // we test it in reverse\n // @TODO if the type is an array (OR) then what?\n // we need to take into account this could be an array\n const c = value.filter(v => !combineFn(type)(v))\n return !(c.length > 0)\n }\n return false;\n}\n\n/**\n * check if it matches the array. pattern\n * @param {string} type\n * @return {boolean|array} false means NO, always return array\n */\nexport const isArrayLike = function(type) {\n // @TODO could that have something like array<> instead of array.<>? missing the dot?\n // because type script is Array without the dot\n if (type.indexOf(ARRAY_TYPE_LFT) > -1 && type.indexOf(ARRAY_TYPE_RGT) > -1) {\n const _type = type.replace(ARRAY_TYPE_LFT, '').replace(ARRAY_TYPE_RGT, '')\n if (_type.indexOf(OR_SEPERATOR)) {\n return _type.split(OR_SEPERATOR)\n }\n return [_type]\n }\n return false;\n}\n\n/**\n * we might encounter something like array. then we need to take it apart\n * @param {object} p the prepared object for processing\n * @param {string|array} type the type came from \n * @return {boolean} for the filter to operate on\n */\nexport const arrayTypeHandler = function(p, type) {\n const { arg } = p;\n // need a special case to handle the OR type\n // we need to test the args instead of the type(s)\n if (type.length > 1) {\n return !arg.filter(v => (\n !(type.length > type.filter(t => !combineFn(t)(v)).length)\n )).length;\n }\n // type is array so this will be or!\n return type.length > type.filter(t => !checkIsArray(arg, t)).length;\n}\n","// validate object type\nimport { isPlainObject, isUndefined, filter } from 'lodash-es'\nimport combineFn from './combine'\nimport { checkIsArray, isArrayLike, arrayTypeHandler } from './array'\n/**\n * @TODO if provide with the keys then we need to check if the key:value type as well\n * @param {object} value expected\n * @param {array} [keys=null] if it has the keys array to compare as well\n * @return {boolean} true if OK\n */\nexport const checkIsObject = function(value, keys=null) {\n if (isPlainObject(value)) {\n if (!keys) {\n return true;\n }\n if (checkIsArray(keys)) {\n // please note we DON'T care if some is optional\n // plese refer to the contract.json for the keys\n return !keys.filter(key => {\n let _value = value[key.name];\n return !(key.type.length > key.type.filter(type => {\n let tmp;\n if (!isUndefined(_value)) {\n if ((tmp = isArrayLike(type)) !== false) {\n return !arrayTypeHandler({arg: _value}, tmp)\n // return tmp.filter(t => !checkIsArray(_value, t)).length;\n // @TODO there might be an object within an object with keys as well :S\n }\n return !combineFn(type)(_value)\n }\n return true;\n }).length)\n }).length;\n }\n }\n return false;\n}\n\n/**\n * fold this into it's own function to handler different object type\n * @param {object} p the prepared object for process\n * @return {boolean}\n */\nexport const objectTypeHandler = function(p) {\n const { arg, param } = p;\n let _args = [arg];\n if (Array.isArray(param.keys) && param.keys.length) {\n _args.push(param.keys)\n }\n // just simple check\n return checkIsObject.apply(null, _args)\n}\n","// move the index.js code here that make more sense to find where things are\nimport { isUndefined } from 'lodash-es'\nimport {\n checkIsArray,\n isArrayLike,\n arrayTypeHandler,\n objectTypeHandler,\n checkIsObject,\n combineFn,\n notEmpty\n} from './index'\nimport {\n DEFAULT_TYPE,\n ARRAY_TYPE,\n OBJECT_TYPE,\n ARGS_NOT_ARRAY_ERR,\n PARAMS_NOT_ARRAY_ERR,\n EXCEPTION_CASE_ERR,\n UNUSUAL_CASE_ERR\n} from './constants'\nimport { DATA_KEY, ERROR_KEY } from 'jsonql-constants'\nimport { JsonqlError } from 'jsonql-errors'\n\n// import debug from 'debug'\n// const debugFn = debug('jsonql-params-validator:validator')\n// also export this for use in other places\n\n/**\n * We need to handle those optional parameter without a default value\n * @param {object} params from contract.json\n * @return {boolean} for filter operation false is actually OK\n */\nconst optionalHandler = function( params ) {\n const { arg, param } = params;\n if (notEmpty(arg)) {\n // debug('call optional handler', arg, params);\n // loop through the type in param\n return !(param.type.length > param.type.filter(type =>\n validateHandler(type, params)\n ).length)\n }\n return false;\n}\n\n/**\n * actually picking the validator\n * @param {*} type for checking\n * @param {*} value for checking\n * @return {boolean} true on OK\n */\nconst validateHandler = function(type, value) {\n let tmp;\n switch (true) {\n case type === OBJECT_TYPE:\n // debugFn('call OBJECT_TYPE')\n return !objectTypeHandler(value)\n case type === ARRAY_TYPE:\n // debugFn('call ARRAY_TYPE')\n return !checkIsArray(value.arg)\n // @TODO when the type is not present, it always fall through here\n // so we need to find a way to actually pre-check the type first\n // AKA check the contract.json map before running here\n case (tmp = isArrayLike(type)) !== false:\n // debugFn('call ARRAY_LIKE: %O', value)\n return !arrayTypeHandler(value, tmp)\n default:\n return !combineFn(type)(value.arg)\n }\n}\n\n/**\n * it get too longer to fit in one line so break it out from the fn below\n * @param {*} arg value\n * @param {object} param config\n * @return {*} value or apply default value\n */\nconst getOptionalValue = function(arg, param) {\n if (!isUndefined(arg)) {\n return arg;\n }\n return (param.optional === true && !isUndefined(param.defaultvalue) ? param.defaultvalue : null)\n}\n\n/**\n * padding the arguments with defaultValue if the arguments did not provide the value\n * this will be the name export\n * @param {array} args normalized arguments\n * @param {array} params from contract.json\n * @return {array} merge the two together\n */\nexport const normalizeArgs = function(args, params) {\n // first we should check if this call require a validation at all\n // there will be situation where the function doesn't need args and params\n if (!checkIsArray(params)) {\n // debugFn('params value', params)\n throw new JsonqlError(PARAMS_NOT_ARRAY_ERR)\n }\n if (params.length === 0) {\n return [];\n }\n if (!checkIsArray(args)) {\n throw new JsonqlError(ARGS_NOT_ARRAY_ERR)\n }\n // debugFn(args, params);\n // fall through switch\n switch(true) {\n case args.length == params.length: // standard\n return args.map((arg, i) => (\n {\n arg,\n index: i,\n param: params[i]\n }\n ));\n case params[0].variable === true: // using spread syntax\n const type = params[0].type;\n return args.map((arg, i) => (\n {\n arg,\n index: i, // keep the index for reference\n param: params[i] || { type, name: '_' }\n }\n ));\n // with optional defaultValue parameters\n case args.length < params.length:\n return params.map((param, i) => (\n {\n param,\n index: i,\n arg: getOptionalValue(args[i], param),\n optional: param.optional || false\n }\n ));\n // this one pass more than it should have anything after the args.length will be cast as any type\n case args.length > params.length && params.length === 1:\n // this happens when we have those array. type\n let tmp, _type = [ DEFAULT_TYPE ];\n // we only looking at the first one, this might be a @BUG!\n if ((tmp = isArrayLike(params[0].type[0])) !== false) {\n _type = tmp;\n }\n // if not then we fall back to the following\n return args.map((arg, i) => (\n {\n arg,\n index: i,\n param: params[i] || { type: _type, name: '_' }\n }\n ));\n // @TODO find out if there is more cases not cover\n default: // this should never happen\n // debugFn('args', args)\n // debugFn('params', params)\n // this is unknown therefore we just throw it!\n throw new JsonqlError(EXCEPTION_CASE_ERR, { args, params })\n }\n}\n\n// what we want is after the validaton we also get the normalized result\n// which is with the optional property if the argument didn't provide it\n/**\n * process the array of params back to their arguments\n * @param {array} result the params result\n * @return {array} arguments\n */\nconst processReturn = result => result.map(r => r.arg)\n\n/**\n * validator main interface\n * @param {array} args the arguments pass to the method call\n * @param {array} params from the contract for that method\n * @param {boolean} [withResul=false] if true then this will return the normalize result as well\n * @return {array} empty array on success, or failed parameter and reasons\n */\nexport const validateSync = function(args, params, withResult = false) {\n let cleanArgs = normalizeArgs(args, params)\n let checkResult = cleanArgs.filter(p => {\n if (p.param.optional === true) {\n return optionalHandler(p)\n }\n // because array of types means OR so if one pass means pass\n return !(p.param.type.length > p.param.type.filter(\n type => validateHandler(type, p)\n ).length)\n })\n // using the same convention we been using all this time\n return !withResult ? checkResult : {\n [ERROR_KEY]: checkResult,\n [DATA_KEY]: processReturn(cleanArgs)\n }\n}\n\n/**\n * A wrapper method that return promise\n * @param {array} args arguments\n * @param {array} params from contract.json\n * @param {boolean} [withResul=false] if true then this will return the normalize result as well\n * @return {object} promise.then or catch\n */\nexport const validateAsync = function(args, params, withResult = false) {\n return new Promise((resolver, rejecter) => {\n const result = validateSync(args, params, withResult)\n if (withResult) {\n return result[ERROR_KEY].length ? rejecter(result[ERROR_KEY])\n : resolver(result[DATA_KEY])\n }\n // the different is just in the then or catch phrase\n return result.length ? rejecter(result) : resolver([])\n })\n}\n","/**\n * @param {array} arr Array for check\n * @param {*} value target\n * @return {boolean} true on successs\n */\nconst isInArray = function(arr, value) {\n return !!arr.filter(a => a === value).length;\n}\n\nexport default isInArray\n","// breaking the whole thing up to see what cause the multiple calls issue\n\nimport { isFunction, merge, mapValues } from 'lodash-es'\n\nimport {\n TYPE_KEY,\n OPTIONAL_KEY,\n ENUM_KEY,\n ARGS_KEY,\n CHECKER_KEY,\n KEY_WORD\n} from '../constants'\nimport {\n JsonqlEnumError,\n JsonqlTypeError,\n JsonqlCheckerError\n} from 'jsonql-errors'\nimport { checkIsArray } from '../array'\n\n// import debug from 'debug';\n// const debugFn = debug('jsonql-params-validator:options:validation')\n\n/**\n * just make sure it returns an array to use\n * @param {*} arg input\n * @return {array} output\n */\nconst toArray = arg => checkIsArray(arg) ? arg : [arg]\n\n/**\n * DIY in array\n * @param {array} arr to check against\n * @param {*} value to check\n * @return {boolean} true on OK\n */\nconst inArray = (arr, value) => (\n !!arr.filter(v => v === value).length\n)\n\n/**\n * break out to make the code easier to read\n * @param {object} value to process\n * @param {function} cb the validateSync\n * @return {array} empty on success\n */\nfunction validateHandler(value, cb) {\n // cb is the validateSync methods\n let args = [\n [ value[ARGS_KEY] ],\n [{\n [TYPE_KEY]: toArray(value[TYPE_KEY]),\n [OPTIONAL_KEY]: value[OPTIONAL_KEY]\n }]\n ]\n // debugFn('validateHandler', args)\n return Reflect.apply(cb, null, args)\n}\n\n/**\n * Check against the enum value if it's provided\n * @param {*} value to check\n * @param {*} enumv to check against if it's not false\n * @return {boolean} true on OK\n */\nconst enumHandler = (value, enumv) => {\n if (checkIsArray(enumv)) {\n return inArray(enumv, value)\n }\n return true;\n}\n\n/**\n * Allow passing a function to check the value\n * There might be a problem here if the function is incorrect\n * and that will makes it hard to debug what is going on inside\n * @TODO there could be a few feature add to this one under different circumstance\n * @param {*} value to check\n * @param {function} checker for checking\n */\nconst checkerHandler = (value, checker) => {\n try {\n return isFunction(checker) ? checker.apply(null, [value]) : false;\n } catch (e) {\n return false;\n }\n}\n\n/**\n * Taken out from the runValidaton this only validate the required values\n * @param {array} args from the config2argsAction\n * @param {function} cb validateSync\n * @return {array} of configuration values\n */\nfunction runValidationAction(cb) {\n return (value, key) => {\n // debugFn('runValidationAction', key, value)\n if (value[KEY_WORD]) {\n return value[ARGS_KEY]\n }\n const check = validateHandler(value, cb)\n if (check.length) {\n // debugFn('runValidationAction', key, value)\n throw new JsonqlTypeError(key, check)\n }\n if (value[ENUM_KEY] !== false && !enumHandler(value[ARGS_KEY], value[ENUM_KEY])) {\n throw new JsonqlEnumError(key)\n }\n if (value[CHECKER_KEY] !== false && !checkerHandler(value[ARGS_KEY], value[CHECKER_KEY])) {\n throw new JsonqlCheckerError(key)\n }\n return value[ARGS_KEY]\n }\n}\n\n/**\n * @param {object} args from the config2argsAction\n * @param {function} cb validateSync\n * @return {object} of configuration values\n */\nexport default function runValidation(args, cb) {\n const [ argsForValidate, pristineValues ] = args;\n // turn the thing into an array and see what happen here\n // debugFn('_args', argsForValidate)\n const result = mapValues(argsForValidate, runValidationAction(cb))\n return merge(result, pristineValues)\n}\n","// this is port back from the client to share across all projects\nimport { merge } from 'lodash-es'\nimport { prepareArgsForValidation } from './prepare-args-for-validation'\nimport runValidation from './run-validation'\n\n// import debug from 'debug'\n// const debugFn = debug('jsonql-params-validator:check-options-async')\n\n/**\n * Quick transform\n * @param {object} config that one\n * @param {object} appProps mutation configuration options\n * @return {object} put that arg into the args\n */\nconst configToArgs = (config, appProps) => {\n return Promise.resolve(\n prepareArgsForValidation(config, appProps)\n )\n}\n\n/**\n * @param {object} config user provide configuration option\n * @param {object} appProps mutation configuration options\n * @param {object} constProps the immutable configuration options\n * @param {function} cb the validateSync method\n * @return {object} Promise resolve merge config object\n */\nexport default function(config = {}, appProps, constProps, cb) {\n return configToArgs(config, appProps)\n .then(args1 => {\n // debugFn('args', args1)\n return runValidation(args1, cb)\n })\n // next if every thing good then pass to final merging\n .then(args2 => merge({}, args2, constProps))\n}\n","// create function to construct the config entry so we don't need to keep building object\nimport {\n ARGS_KEY,\n TYPE_KEY,\n CHECKER_KEY,\n ENUM_KEY,\n OPTIONAL_KEY,\n ALIAS_KEY\n} from 'jsonql-constants';\nimport { checkIsArray } from '../array';\nimport checkIsBoolean from '../boolean';\nimport { isFunction, isString } from 'lodash-es';\n// import debug from 'debug';\n// const debugFn = debug('jsonql-params-validator:construct-config');\n/**\n * @param {*} args value\n * @param {string} type for value\n * @param {boolean} [optional=false]\n * @param {boolean|array} [enumv=false]\n * @param {boolean|function} [checker=false]\n * @return {object} config entry\n */\nexport default function(args, type, optional=false, enumv=false, checker=false, alias=false) {\n let base = {\n [ARGS_KEY]: args,\n [TYPE_KEY]: type\n };\n if (optional === true) {\n base[OPTIONAL_KEY] = true;\n }\n if (checkIsArray(enumv)) {\n base[ENUM_KEY] = enumv;\n }\n if (isFunction(checker)) {\n base[CHECKER_KEY] = checker;\n }\n if (isString(alias)) {\n base[ALIAS_KEY] = alias;\n }\n return base;\n};\n","// export also create wrapper methods\nimport checkOptionsAsync from './check-options-async'\nimport checkOptionsSync from './check-options-sync'\nimport constructConfigFn from './construct-config'\nimport {\n ENUM_KEY,\n CHECKER_KEY,\n ALIAS_KEY,\n OPTIONAL_KEY\n} from 'jsonql-constants'\n\n// import debug from 'debug';\n// const debugFn = debug('jsonql-params-validator:options:index');\n\n/**\n * This has a different interface\n * @param {*} value to supply\n * @param {string|array} type for checking\n * @param {object} params to map against the config check\n * @param {array} params.enumv NOT enum\n * @param {boolean} params.optional false then nothing\n * @param {function} params.checker need more work on this one later\n * @param {string} params.alias mostly for cmd\n */\nconst createConfig = (value, type, params = {}) => {\n // Note the enumv not ENUM\n // const { enumv, optional, checker, alias } = params;\n // let args = [value, type, optional, enumv, checker, alias];\n const {\n [OPTIONAL_KEY]: o,\n [ENUM_KEY]: e,\n [CHECKER_KEY]: c,\n [ALIAS_KEY]: a\n } = params;\n return constructConfigFn.apply(null, [value, type, o, e, c, a])\n}\n\n// for testing purpose\nconst JSONQL_PARAMS_VALIDATOR_INFO = '__PLACEHOLDER__';\n\n/**\n * We recreate the method here to avoid the circlar import\n * @param {object} config user supply configuration\n * @param {object} appProps mutation options\n * @param {object} [constantProps={}] optional: immutation options\n * @return {object} all checked configuration\n */\nconst checkConfigAsync = function(validateSync) {\n return function(config, appProps, constantProps= {}) {\n return checkOptionsAsync(config, appProps, constantProps, validateSync)\n }\n}\n\n// copy of above but it's sync\nconst checkConfig = function(validateSync) {\n return function(config, appProps, constantProps = {}) {\n return checkOptionsSync(config, appProps, constantProps, validateSync)\n }\n}\n\n// re-export\nexport {\n createConfig,\n constructConfigFn,\n checkConfigAsync,\n checkConfig,\n JSONQL_PARAMS_VALIDATOR_INFO\n}\n","// since this need to use everywhere might as well include in the validator\nimport { QUERY_NAME, MUTATION_NAME, SOCKET_NAME } from 'jsonql-constants'\nimport checkKeyInObject from './check-key-in-object'\nimport { checkIsObject } from './object'\n\nexport default function(contract) {\n return checkIsObject(contract)\n && (\n checkKeyInObject(contract, QUERY_NAME)\n || checkKeyInObject(contract, MUTATION_NAME)\n || checkKeyInObject(contract, SOCKET_NAME)\n )\n}\n","// craete several helper function to construct / extract the payload\n// and make sure they are all the same\nimport {\n PAYLOAD_PARAM_NAME,\n CONDITION_PARAM_NAME,\n RESOLVER_PARAM_NAME,\n QUERY_ARG_NAME\n} from 'jsonql-constants'\nimport { JsonqlValidationError } from 'jsonql-errors'\n\nimport isString from './string'\nimport { checkIsArray } from './array'\nimport { checkIsObject } from './object'\n\n// make sure it's an object\nconst formatPayload = payload => isString(payload) ? JSON.parse(payload) : payload;\n\n/**\n * Get name from the payload (ported back from jsonql-koa)\n * @param {*} payload to extract from\n * @return {string} name\n */\nexport function getNameFromPayload(payload) {\n return Object.keys(payload)[0]\n}\n\n/**\n * @param {string} resolverName name of function\n * @param {array} [args=[]] from the ...args\n * @return {object} formatted argument\n */\nexport function createQuery(resolverName, args = []) {\n if (isString(resolverName) && checkIsArray(args)) {\n return {\n [resolverName]: {\n [QUERY_ARG_NAME]: args\n }\n }\n }\n throw new JsonqlValidationError(`[createQuery] expect resolverName to be string and args to be array!`, { resolverName, args })\n}\n\n// string version of the above\nexport function createQueryStr(resolverName, args) {\n return JSON.stringify(createQuery(resolverName, args))\n}\n\n/**\n * @param {string} resolverName name of function\n * @param {*} payload to send\n * @param {object} [condition={}] for what\n * @return {object} formatted argument\n */\nexport function createMutation(resolverName, payload, condition = {}) {\n if (isString(resolverName)) {\n return {\n [resolverName]: {\n [PAYLOAD_PARAM_NAME]: payload,\n [CONDITION_PARAM_NAME]: condition\n }\n }\n }\n throw new JsonqlValidationError(`[createMutation] expect resolverName to be string!`, { resolverName, payload, condition })\n}\n\n// string version of above\nexport function createMutationStr(resolverName, payload, condition) {\n return JSON.stringify(createMutation(resolverName, payload, condition))\n}\n\n/**\n * Further break down from method below for use else where\n * @param {string} resolverName name of fn\n * @param {object} payload payload\n * @return {object|boolean} false on failed\n */\nexport function getQueryFromArgs(resolverName, payload) {\n if (resolverName && checkIsObject(payload)) {\n const args = payload[resolverName];\n if (args[QUERY_ARG_NAME]) {\n return {\n [RESOLVER_PARAM_NAME]: resolverName,\n [QUERY_ARG_NAME]: args[QUERY_ARG_NAME]\n }\n }\n }\n return false;\n}\n\n/**\n * extra the payload back\n * @param {*} payload from http call\n * @return {object} resolverName and args\n */\nexport function getQueryFromPayload(payload) {\n const p = formatPayload(payload);\n const resolverName = getNameFromPayload(p)\n const result = getQueryFromArgs(resolverName, p)\n if (result !== false) {\n return result;\n }\n throw new JsonqlValidationError('[getQueryArgs] Payload is malformed!', payload)\n}\n\n/**\n * Further break down from method below for use else where\n * @param {string} resolverName name of fn\n * @param {object} payload payload\n * @return {object|boolean} false on failed\n */\nexport function getMutationFromArgs(resolverName, payload) {\n if (resolverName && checkIsObject(payload)) {\n const args = payload[resolverName]\n if (args) {\n return {\n [RESOLVER_PARAM_NAME]: resolverName,\n [PAYLOAD_PARAM_NAME]: args[PAYLOAD_PARAM_NAME],\n [CONDITION_PARAM_NAME]: args[CONDITION_PARAM_NAME]\n }\n }\n }\n return false;\n}\n\n/**\n * @param {object} payload\n * @return {object} resolverName, payload, conditon\n */\nexport function getMutationFromPayload(payload) {\n const p = formatPayload(payload);\n const resolverName = getNameFromPayload(p)\n const result = getMutationFromArgs(resolverName, p)\n if (result !== false) {\n return result;\n }\n throw new JsonqlValidationError('[getMutationArgs] Payload is malformed!', payload)\n}\n","// export\nimport {\n checkIsObject,\n notEmpty,\n checkIsAny,\n checkIsString,\n checkIsBoolean,\n checkIsNumber,\n checkIsArray\n} from './src'\n// PIA syntax\nexport const isObject = checkIsObject;\nexport const isAny = checkIsAny;\nexport const isString = checkIsString;\nexport const isBoolean = checkIsBoolean;\nexport const isNumber = checkIsNumber;\nexport const isArray = checkIsArray;\nexport const isNotEmpty = notEmpty;\n\nimport * as validator from './src/validator'\n\nexport const normalizeArgs = validator.normalizeArgs;\nexport const validateSync = validator.validateSync;\nexport const validateAsync = validator.validateAsync;\n\n// configuration checking\n\nimport * as jsonqlOptions from './src/options'\n\nexport const JSONQL_PARAMS_VALIDATOR_INFO = jsonqlOptions.JSONQL_PARAMS_VALIDATOR_INFO;\n\nexport const createConfig = jsonqlOptions.createConfig;\nexport const constructConfig = jsonqlOptions.constructConfigFn;\n\nexport const checkConfigAsync = jsonqlOptions.checkConfigAsync(validator.validateSync)\nexport const checkConfig = jsonqlOptions.checkConfig(validator.validateSync)\n\nimport isInArray from './src/is-in-array'\n\nexport const inArray = isInArray;\n\nimport checkKeyInObject from './src/check-key-in-object'\n\nexport const isKeyInObject = checkKeyInObject;\n\nimport checkIsContract from './src/check-is-contract'\n\nexport const isContract = checkIsContract;\n\n// add in v1.3.0\n\nimport * as paramsApi from './src/params-api'\n\nexport const createQuery = paramsApi.createQuery;\nexport const createQueryStr = paramsApi.createQueryStr;\nexport const createMutation = paramsApi.createMutation;\nexport const createMutationStr = paramsApi.createMutationStr;\nexport const getQueryFromArgs = paramsApi.getQueryFromArgs;\nexport const getQueryFromPayload = paramsApi.getQueryFromPayload;\nexport const getMutationFromArgs = paramsApi.getMutationFromArgs;\nexport const getMutationFromPayload = paramsApi.getMutationFromPayload;\nexport const getNameFromPayload = paramsApi.getNameFromPayload;\n","// This is ported back from ws-server and it will get use in the server / client side\nimport { isKeyInObject } from 'jsonql-params-validator'\n\nfunction extractSocketPart(contract) {\n if (isKeyInObject(contract, 'socket')) {\n return contract.socket;\n }\n return contract;\n}\n\n/**\n * @BUG we should check the socket part instead of expect the downstream to read the menu!\n * We only need this when the enableAuth is true otherwise there is only one namespace\n * @param {object} contract the socket part of the contract file\n * @return {object} 1. remap the contract using the namespace --> resolvers\n * 2. the size of the object (1 all private, 2 mixed public with private)\n * 3. which namespace is public\n */\nexport default function groupByNamespace(contract) {\n let socket = extractSocketPart(contract)\n\n let nspSet = {};\n let size = 0;\n let publicNamespace;\n for (let resolverName in socket) {\n let params = socket[resolverName];\n let { namespace } = params;\n if (namespace) {\n if (!nspSet[namespace]) {\n ++size;\n nspSet[namespace] = {};\n }\n nspSet[namespace][resolverName] = params;\n if (!publicNamespace) {\n if (params.public) {\n publicNamespace = namespace;\n }\n }\n }\n }\n return { size, nspSet, publicNamespace }\n}\n","// This is ported back from ws-client\n// the idea if from https://decembersoft.com/posts/promises-in-serial-with-array-reduce/\n/**\n * previously we already make sure the order of the namespaces\n * and attach the auth client to it\n * @param {array} promises array of unresolved promises\n * @return {object} promise resolved with the array of promises resolved results\n */\nexport default function chainPromises(promises) {\n return promises.reduce((promiseChain, currentTask) => (\n promiseChain.then(chainResults => (\n currentTask.then(currentResult => (\n [...chainResults, currentResult]\n ))\n ))\n ), Promise.resolve([]))\n}\n","/**\n * The code was extracted from:\n * https://github.com/davidchambers/Base64.js\n */\n\nvar chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n\nfunction InvalidCharacterError(message) {\n this.message = message;\n}\n\nInvalidCharacterError.prototype = new Error();\nInvalidCharacterError.prototype.name = 'InvalidCharacterError';\n\nfunction polyfill (input) {\n var str = String(input).replace(/=+$/, '');\n if (str.length % 4 == 1) {\n throw new InvalidCharacterError(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n for (\n // initialize result and counters\n var bc = 0, bs, buffer, idx = 0, output = '';\n // get next character\n buffer = str.charAt(idx++);\n // character found in table? initialize bit storage and add its ascii value;\n ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,\n // and if not first of each 4 characters,\n // convert the first 8 bits to one ascii character\n bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0\n ) {\n // try to find character in table (0-63, not found => -1)\n buffer = chars.indexOf(buffer);\n }\n return output;\n}\n\n\nmodule.exports = typeof window !== 'undefined' && window.atob && window.atob.bind(window) || polyfill;\n","// ws client using native WebSocket\nimport { JsonqlValidationError } from 'jsonql-errors';\n\nexport default function getWS() {\n switch(true) {\n case (typeof WebSocket !== 'undefined'):\n return WebSocket;\n case (typeof MozWebSocket !== 'undefined'):\n return MozWebSocket;\n // case (typeof global !== 'undefined'):\n // return global.WebSocket || global.MozWebSocket;\n case (typeof window !== 'undefined'):\n return window.WebSocket || window.MozWebSocket;\n // case (typeof self !== 'undefined'):\n // return self.WebSocket || self.MozWebSocket;\n default:\n throw new JsonqlValidationError('WebSocket is NOT SUPPORTED!')\n }\n}\n","// constants\n\nimport {\n EMIT_REPLY_TYPE,\n JS_WS_SOCKET_IO_NAME,\n JS_WS_NAME,\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME\n} from 'jsonql-constants'\n\nconst SOCKET_IO = JS_WS_SOCKET_IO_NAME;\nconst WS = JS_WS_NAME;\n\nconst AVAILABLE_SERVERS = [SOCKET_IO, WS]\n\nconst SOCKET_NOT_DEFINE_ERR = 'socket is not define in the contract file!';\n\nconst SERVER_NOT_SUPPORT_ERR = 'is not supported server name!';\n\nconst MISSING_PROP_ERR = 'Missing property in contract!';\n\nconst UNKNOWN_CLIENT_ERR = 'Unknown client type!';\n\nconst EMIT_EVT = EMIT_REPLY_TYPE;\n\nconst NAMESPACE_KEY = 'namespaceMap';\n\nconst UNKNOWN_RESULT = 'UKNNOWN RESULT!';\n\nconst NOT_ALLOW_OP = 'This operation is not allow!';\n\nconst MY_NAMESPACE = 'myNamespace'\n\nexport {\n SOCKET_IO,\n WS,\n AVAILABLE_SERVERS,\n SOCKET_NOT_DEFINE_ERR,\n SERVER_NOT_SUPPORT_ERR,\n MISSING_PROP_ERR,\n UNKNOWN_CLIENT_ERR,\n EMIT_EVT,\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME,\n NAMESPACE_KEY,\n UNKNOWN_RESULT,\n NOT_ALLOW_OP,\n MY_NAMESPACE\n}\n","// generate the web socket connect client for browser\nimport {\n socketIoRoundtripLogin,\n socketIoClientAsync,\n socketIoHandshakeLogin,\n wsAuthClient,\n wsClient\n} from 'jsonql-jwt'\n\nimport { isString } from 'jsonql-params-validator'\nimport { JsonqlError } from 'jsonql-errors'\nimport { SOCKET_IO, WS } from './constants'\n// import { IO_ROUNDTRIP_LOGIN, IO_HANDSHAKE_LOGIN } from 'jsonql-constants'\nimport getDebug from './get-debug'\nconst debug = getDebug('client-generator')\n\n/**\n * create the web socket client\n * @param {object} payload passing\n * @return {object} just mutate it then pass it on\n */\nexport default function clientGenerator({opts, nspMap, ee}) {\n switch (opts.serverType) {\n case SOCKET_IO:\n opts.nspClient = (...args) => (\n Reflect.apply(socketIoClientAsync, null, [io, ...args])\n )\n if (isString(opts.useJwt)) {\n opts.nspAuthClient = (...args) => (\n Reflect.apply(socketIoRoundtripLogin, null, [io, ...args])\n )\n } else {\n opts.nspAuthClient = (...args) => (\n Reflect.apply(socketIoHandshakeLogin, null, [io, ...args])\n )\n }\n break;\n case WS:\n opts.nspClient = wsClient;\n opts.nspAuthClient = wsAuthClient;\n break;\n default:\n throw new JsonqlError(`Unknown serverType: ${opts.serverType}`)\n }\n return {opts, nspMap, ee}\n}\n","// since both the ws and io version are\n// pre-defined in the client-generator\n// and this one will have the same parameters\n// and the callback is identical\nimport getDebug from './get-debug'\nconst debugFn = getDebug('create-nsp-client')\n/**\n * wrapper method to create a nsp without login\n * @param {string|boolean} namespace namespace url could be false\n * @param {object} opts configuration\n * @return {object} ws client instance\n */\nconst nspClient = (namespace, opts) => {\n const { wssPath, wsOptions, hostname } = opts;\n const url = namespace ? [hostname, namespace].join('/') : wssPath;\n return opts.nspClient(url, wsOptions)\n}\n\n/**\n * wrapper method to create a nsp with token auth\n * @param {string} namespace namespace url\n * @param {object} opts configuration\n * @return {object} ws client instance\n */\nconst nspAuthClient = (namespace, opts) => {\n const { wssPath, token, wsOptions, hostname } = opts;\n const url = namespace ? [hostname, namespace].join('/') : wssPath;\n return opts.nspAuthClient(url, token, wsOptions)\n}\n\nexport {\n nspClient,\n nspAuthClient\n}\n","/**\n * generate a 32bit hash based on the function.toString()\n * _from http://stackoverflow.com/questions/7616461/generate-a-hash-_from-string-in-javascript-jquery\n * @param {string} s the converted to string function\n * @return {string} the hashed function string\n */\nexport default function hashCode(s) {\n\treturn s.split(\"\").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0)\n}\n","// this is the new implementation without the hash key\n// only using Map and Set instead\nimport {\n NB_EVENT_SERVICE_PRIVATE_STORE,\n NB_EVENT_SERVICE_PRIVATE_LAZY\n} from './store'\nimport genHaskKey from './hash-code.js'\n// export\nexport default class EventService {\n /**\n * class constructor\n */\n constructor(config = {}) {\n if (config.logger && typeof config.logger === 'function') {\n this.logger = config.logger;\n }\n this.keep = config.keep;\n // for the $done setter\n this.result = config.keep ? [] : null;\n // we need to init the store first otherwise it could be a lot of checking later\n this.normalStore = new Map()\n this.lazyStore = new Map()\n }\n\n /**\n * logger function for overwrite\n */\n logger() {}\n\n //////////////////////////\n // PUBLIC METHODS //\n //////////////////////////\n\n /**\n * Register your evt handler, note we don't check the type here,\n * we expect you to be sensible and know what you are doing.\n * @param {string} evt name of event\n * @param {function} callback bind method --> if it's array or not\n * @param {object} [context=null] to execute this call in\n * @return {number} the size of the store\n */\n $on(evt , callback , context = null) {\n const type = 'on';\n this.validate(evt, callback)\n // first need to check if this evt is in lazy store\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register first then call later\n if (lazyStoreContent === false) {\n this.logger('$on', `${evt} callback is not in lazy store`)\n // @TODO we need to check if there was other listener to this\n // event and are they the same type then we could solve that\n // register the different type to the same event name\n\n return this.addToNormalStore(evt, type, callback, context)\n }\n this.logger('$on', `${evt} found in lazy store`)\n // this is when they call $trigger before register this callback\n let size = 0;\n lazyStoreContent.forEach(content => {\n let [ payload, ctx, t ] = content;\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.run(callback, payload, context || ctx)\n size += this.addToNormalStore(evt, type, callback, context || ctx)\n })\n return size;\n }\n\n /**\n * once only registered it once, there is no overwrite option here\n * @NOTE change in v1.3.0 $once can add multiple listeners\n * but once the event fired, it will remove this event (see $only)\n * @param {string} evt name\n * @param {function} callback to execute\n * @param {object} [context=null] the handler execute in\n * @return {boolean} result\n */\n $once(evt , callback , context = null) {\n this.validate(evt, callback)\n const type = 'once';\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register before call $trigger\n let nStore = this.normalStore;\n if (lazyStoreContent === false) {\n this.logger('$once', `${evt} not in the lazy store`)\n // v1.3.0 $once now allow to add multiple listeners\n return this.addToNormalStore(evt, type, callback, context)\n } else {\n // now this is the tricky bit\n // there is a potential bug here that cause by the developer\n // if they call $trigger first, the lazy won't know it's a once call\n // so if in the middle they register any call with the same evt name\n // then this $once call will be fucked - add this to the documentation\n this.logger('$once', lazyStoreContent)\n const list = Array.from(lazyStoreContent)\n // should never have more than 1\n const [ payload, ctx, t ] = list[0]\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.run(callback, payload, context || ctx)\n // remove this evt from store\n this.$off(evt)\n }\n }\n\n /**\n * This one event can only bind one callbackback\n * @param {string} evt event name\n * @param {function} callback event handler\n * @param {object} [context=null] the context the event handler execute in\n * @return {boolean} true bind for first time, false already existed\n */\n $only(evt, callback, context = null) {\n this.validate(evt, callback)\n const type = 'only';\n let added = false;\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register before call $trigger\n let nStore = this.normalStore;\n if (!nStore.has(evt)) {\n this.logger(`$only`, `${evt} add to store`)\n added = this.addToNormalStore(evt, type, callback, context)\n }\n if (lazyStoreContent !== false) {\n // there are data store in lazy store\n this.logger('$only', `${evt} found data in lazy store to execute`)\n const list = Array.from(lazyStoreContent)\n // $only allow to trigger this multiple time on the single handler\n list.forEach( l => {\n const [ payload, ctx, t ] = l;\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.run(callback, payload, context || ctx)\n })\n }\n return added;\n }\n\n /**\n * $only + $once this is because I found a very subtile bug when we pass a\n * resolver, rejecter - and it never fire because that's OLD adeed in v1.4.0\n * @param {string} evt event name\n * @param {function} callback to call later\n * @param {object} [context=null] exeucte context\n * @return {void}\n */\n $onlyOnce(evt, callback, context = null) {\n this.validate(evt, callback)\n const type = 'onlyOnce';\n let added = false;\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register before call $trigger\n let nStore = this.normalStore;\n if (!nStore.has(evt)) {\n this.logger(`$onlyOnce`, `${evt} add to store`)\n added = this.addToNormalStore(evt, type, callback, context)\n }\n if (lazyStoreContent !== false) {\n // there are data store in lazy store\n this.logger('$onlyOnce', lazyStoreContent)\n const list = Array.from(lazyStoreContent)\n // should never have more than 1\n const [ payload, ctx, t ] = list[0]\n if (t && t !== 'onlyOnce') {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.run(callback, payload, context || ctx)\n // remove this evt from store\n this.$off(evt)\n }\n return added;\n }\n\n /**\n * This is a shorthand of $off + $on added in V1.5.0\n * @param {string} evt event name\n * @param {function} callback to exeucte\n * @param {object} [context = null] or pass a string as type\n * @param {string} [type=on] what type of method to replace\n * @return {}\n */\n $replace(evt, callback, context = null, type = 'on') {\n if (this.validateType(type)) {\n this.$off(evt)\n let method = this['$' + type]\n return Reflect.apply(method, this, [evt, callback, context])\n }\n throw new Error(`${type} is not supported!`)\n }\n\n /**\n * trigger the event\n * @param {string} evt name NOT allow array anymore!\n * @param {mixed} [payload = []] pass to fn\n * @param {object|string} [context = null] overwrite what stored\n * @param {string} [type=false] if pass this then we need to add type to store too\n * @return {number} if it has been execute how many times\n */\n $trigger(evt , payload = [] , context = null, type = false) {\n this.validateEvt(evt)\n let found = 0;\n // first check the normal store\n let nStore = this.normalStore;\n this.logger('$trigger', nStore)\n if (nStore.has(evt)) {\n this.logger('$trigger', evt, 'found')\n let nSet = Array.from(nStore.get(evt))\n let ctn = nSet.length;\n let hasOnce = false;\n let hasOnly = false;\n for (let i=0; i < ctn; ++i) {\n ++found;\n // this.logger('found', found)\n let [ _, callback, ctx, type ] = nSet[i]\n this.run(callback, payload, context || ctx)\n if (type === 'once' || type === 'onlyOnce') {\n hasOnce = true;\n }\n }\n if (hasOnce) {\n nStore.delete(evt)\n }\n return found;\n }\n // now this is not register yet\n this.addToLazyStore(evt, payload, context, type)\n return found;\n }\n\n /**\n * this is an alias to the $trigger\n * @NOTE breaking change in V1.6.0 we swap the parameter around\n * @param {string} evt event name\n * @param {*} params pass to the callback\n * @param {string} type of call\n * @param {object} context what context callback execute in\n * @return {*} from $trigger\n */\n $call(evt, params, type = false, context = null) {\n let args = [evt, params]\n args.push(context, type)\n return Reflect.apply(this.$trigger, this, args)\n }\n\n /**\n * remove the evt from all the stores\n * @param {string} evt name\n * @return {boolean} true actually delete something\n */\n $off(evt) {\n this.validateEvt(evt)\n let stores = [ this.lazyStore, this.normalStore ]\n let found = false;\n stores.forEach(store => {\n if (store.has(evt)) {\n found = true;\n store.delete(evt)\n }\n })\n return found;\n }\n\n /**\n * return all the listener from the event\n * @param {string} evtName event name\n * @param {boolean} [full=false] if true then return the entire content\n * @return {array|boolean} listerner(s) or false when not found\n */\n $get(evt, full = false) {\n this.validateEvt(evt)\n let store = this.normalStore;\n if (store.has(evt)) {\n return Array\n .from(store.get(evt))\n .map( l => {\n if (full) {\n return l;\n }\n let [key, callback, ] = l;\n return callback;\n })\n }\n return false;\n }\n\n /**\n * store the return result from the run\n * @param {*} value whatever return from callback\n */\n set $done(value) {\n this.logger('set $done', value)\n if (this.keep) {\n this.result.push(value)\n } else {\n this.result = value;\n }\n }\n\n /**\n * @TODO is there any real use with the keep prop?\n * getter for $done\n * @return {*} whatever last store result\n */\n get $done() {\n if (this.keep) {\n this.logger(this.result)\n return this.result[this.result.length - 1]\n }\n return this.result;\n }\n\n /////////////////////////////\n // PRIVATE METHODS //\n /////////////////////////////\n\n /**\n * validate the event name\n * @param {string} evt event name\n * @return {boolean} true when OK\n */\n validateEvt(evt) {\n if (typeof evt === 'string') {\n return true;\n }\n throw new Error(`event name must be string type!`)\n }\n\n /**\n * Simple quick check on the two main parameters\n * @param {string} evt event name\n * @param {function} callback function to call\n * @return {boolean} true when OK\n */\n validate(evt, callback) {\n if (this.validateEvt(evt)) {\n if (typeof callback === 'function') {\n return true;\n }\n }\n throw new Error(`callback required to be function type!`)\n }\n\n /**\n * Check if this type is correct or not added in V1.5.0\n * @param {string} type for checking\n * @return {boolean} true on OK\n */\n validateType(type) {\n const types = ['on', 'only', 'once', 'onlyOnce']\n return !!types.filter(t => type === t).length;\n }\n\n /**\n * Run the callback\n * @param {function} callback function to execute\n * @param {array} payload for callback\n * @param {object} ctx context or null\n * @return {void} the result store in $done\n */\n run(callback, payload, ctx) {\n this.logger('run', callback, payload, ctx)\n this.$done = Reflect.apply(callback, ctx, this.toArray(payload))\n }\n\n /**\n * Take the content out and remove it from store id by the name\n * @param {string} evt event name\n * @param {string} [storeName = lazyStore] name of store\n * @return {object|boolean} content or false on not found\n */\n takeFromStore(evt, storeName = 'lazyStore') {\n let store = this[storeName]; // it could be empty at this point\n if (store) {\n this.logger('takeFromStore', storeName, store)\n if (store.has(evt)) {\n let content = store.get(evt)\n this.logger('takeFromStore', content)\n store.delete(evt)\n return content;\n }\n return false;\n }\n throw new Error(`${storeName} is not supported!`)\n }\n\n /**\n * The add to store step is similar so make it generic for resuse\n * @param {object} store which store to use\n * @param {string} evt event name\n * @param {spread} args because the lazy store and normal store store different things\n * @return {array} store and the size of the store\n */\n addToStore(store, evt, ...args) {\n let fnSet;\n if (store.has(evt)) {\n this.logger('addToStore', `${evt} existed`)\n fnSet = store.get(evt)\n } else {\n this.logger('addToStore', `create new Set for ${evt}`)\n // this is new\n fnSet = new Set()\n }\n // lazy only store 2 items - this is not the case in V1.6.0 anymore\n // we need to check the first parameter is string or not\n if (args.length > 2) {\n if (Array.isArray(args[0])) { // lazy store\n // check if this type of this event already register in the lazy store\n let [,,t] = args;\n if (!this.checkTypeInLazyStore(evt, t)) {\n fnSet.add(args)\n }\n } else {\n if (!this.checkContentExist(args, fnSet)) {\n this.logger('addToStore', `insert new`, args)\n fnSet.add(args)\n }\n }\n } else { // add straight to lazy store\n fnSet.add(args)\n }\n store.set(evt, fnSet)\n return [store, fnSet.size]\n }\n\n /**\n * @param {array} args for compare\n * @param {object} fnSet A Set to search from\n * @return {boolean} true on exist\n */\n checkContentExist(args, fnSet) {\n let list = Array.from(fnSet)\n return !!list.filter(l => {\n let [hash,] = l;\n if (hash === args[0]) {\n return true;\n }\n return false;\n }).length;\n }\n\n /**\n * get the existing type to make sure no mix type add to the same store\n * @param {string} evtName event name\n * @param {string} type the type to check\n * @return {boolean} true you can add, false then you can't add this type\n */\n checkTypeInStore(evtName, type) {\n this.validateEvt(evtName)\n this.validateEvt(type)\n let all = this.$get(evtName, true)\n if (all === false) {\n // pristine it means you can add\n return true;\n }\n // it should only have ONE type in ONE event store\n return !all.filter(list => {\n let [ ,,,t ] = list;\n return type !== t;\n }).length;\n }\n\n /**\n * This is checking just the lazy store because the structure is different\n * therefore we need to use a new method to check it\n */\n checkTypeInLazyStore(evtName, type) {\n this.validateEvt(evtName)\n this.validateEvt(type)\n let store = this.lazyStore.get(evtName)\n this.logger('checkTypeInLazyStore', store)\n if (store) {\n return !!Array\n .from(store)\n .filter(l => {\n let [,,t] = l;\n return t !== type;\n }).length\n }\n return false;\n }\n\n /**\n * wrapper to re-use the addToStore,\n * V1.3.0 add extra check to see if this type can add to this evt\n * @param {string} evt event name\n * @param {string} type on or once\n * @param {function} callback function\n * @param {object} context the context the function execute in or null\n * @return {number} size of the store\n */\n addToNormalStore(evt, type, callback, context = null) {\n this.logger('addToNormalStore', evt, type, 'add to normal store')\n // @TODO we need to check the existing store for the type first!\n if (this.checkTypeInStore(evt, type)) {\n this.logger(`${type} can add to ${evt} store`)\n let key = this.hashFnToKey(callback)\n let args = [this.normalStore, evt, key, callback, context, type]\n let [_store, size] = Reflect.apply(this.addToStore, this, args)\n this.normalStore = _store;\n return size;\n }\n return false;\n }\n\n /**\n * Add to lazy store this get calls when the callback is not register yet\n * so we only get a payload object or even nothing\n * @param {string} evt event name\n * @param {array} payload of arguments or empty if there is none\n * @param {object} [context=null] the context the callback execute in\n * @param {string} [type=false] register a type so no other type can add to this evt\n * @return {number} size of the store\n */\n addToLazyStore(evt, payload = [], context = null, type = false) {\n // this is add in V1.6.0\n // when there is type then we will need to check if this already added in lazy store\n // and no other type can add to this lazy store\n let args = [this.lazyStore, evt, this.toArray(payload), context]\n if (type) {\n args.push(type)\n }\n let [_store, size] = Reflect.apply(this.addToStore, this, args)\n this.lazyStore = _store;\n return size;\n }\n\n /**\n * make sure we store the argument correctly\n * @param {*} arg could be array\n * @return {array} make sured\n */\n toArray(arg) {\n return Array.isArray(arg) ? arg : [arg];\n }\n\n /**\n * setter to store the Set in private\n * @param {object} obj a Set\n */\n set normalStore(obj) {\n NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj)\n }\n\n /**\n * @return {object} Set object\n */\n get normalStore() {\n return NB_EVENT_SERVICE_PRIVATE_STORE.get(this)\n }\n\n /**\n * setter to store the Set in lazy store\n * @param {object} obj a Set\n */\n set lazyStore(obj) {\n NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj)\n }\n\n /**\n * @return {object} the lazy store Set\n */\n get lazyStore() {\n return NB_EVENT_SERVICE_PRIVATE_LAZY.get(this)\n }\n\n /**\n * generate a hashKey to identify the function call\n * The build-in store some how could store the same values!\n * @param {function} fn the converted to string function\n * @return {string} hashKey\n */\n hashFnToKey(fn) {\n return genHaskKey(fn.toString()) + '';\n }\n\n}\n","// default\nimport NBEventService from './src/event-service'\n\nexport default NBEventService\n","// mapping the resolver to their respective nsp\n\nimport { JSONQL_PATH } from 'jsonql-constants'\nimport { groupByNamespace } from 'jsonql-jwt'\nimport { JsonqlResolverNotFoundError } from 'jsonql-errors'\n\nimport { MISSING_PROP_ERR } from './constants'\nimport getDebug from './get-debug'\nconst debug = getDebug('process-contract')\n\n/**\n * Just make sure the object contain what we are looking for\n * @param {object} opts configuration from checkOptions\n * @return {object} the target content\n */\nconst getResolverList = contract => {\n if (contract) {\n const { socket } = contract;\n if (socket) {\n return socket;\n }\n }\n throw new JsonqlResolverNotFoundError(MISSING_PROP_ERR)\n}\n\n/**\n * process the contract first\n * @param {object} opts configuration\n * @return {object} sorted list\n */\nexport default function processContract(opts) {\n const { contract, enableAuth } = opts;\n if (enableAuth) {\n return groupByNamespace(contract)\n }\n return {\n nspSet: { [JSONQL_PATH]: getResolverList(contract) },\n publicNamespace: JSONQL_PATH,\n size: 1 // this prop is pretty meaningless now\n }\n}\n","// export the util methods\nimport { QUERY_ARG_NAME, JS_WS_SOCKET_IO_NAME } from 'jsonql-constants'\nimport getNamespaceInOrder from './get-namespace-in-order'\nimport checkOptions from './check-options'\nimport ee from './ee'\nimport * as constants from './constants'\nimport getDebug from './get-debug'\n\nimport processContract from './process-contract'\nimport { isArray } from 'jsonql-params-validator'\n\nconst toArray = (arg) => isArray(arg) ? arg : [arg];\n\n/**\n * very simple tool to create the event name\n * @param {string} [...args] spread\n * @return {string} join by _\n */\nconst createEvt = (...args) => args.join('_')\n\n/**\n * Unbind the event\n * @param {object} ee EventEmitter\n * @param {string} namespace\n * @return {void}\n */\nconst clearMainEmitEvt = (ee, namespace) => {\n let nsps = isArray(namespace) ? namespace : [namespace]\n nsps.forEach(n => {\n ee.$off(createEvt(n, constants.EMIT_EVT))\n })\n}\n\n/**\n * @param {*} args arguments to send\n *@return {object} formatted payload\n */\nconst formatPayload = (args) => (\n { [QUERY_ARG_NAME]: args }\n)\n\n/**\n * @param {object} nsps namespace as key\n * @param {string} type of server\n */\nconst disconnect = (nsps, type = JS_WS_SOCKET_IO_NAME) => {\n try {\n const method = type === JS_WS_SOCKET_IO_NAME ? 'disconnect' : 'terminate';\n for (let namespace in nsps) {\n let nsp = nsps[namespace]\n if (nsp && nsp[method]) {\n Reflect.apply(nsp[method], null, [])\n }\n }\n } catch(e) {\n // socket.io throw a this.destroy of undefined?\n console.error('disconnect', e)\n }\n}\n\n\nexport {\n getNamespaceInOrder,\n createEvt,\n clearMainEmitEvt,\n checkOptions,\n ee,\n constants,\n getDebug,\n processContract,\n toArray,\n formatPayload,\n disconnect\n}\n","// @TODO port what is in the ws-main-handler\n// because all the client side call are via the ee\n// and that makes it re-usable between different client setup\nimport {\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME,\n EMIT_EVT,\n SOCKET_IO,\n WS\n} from './utils/constants'\nimport {\n LOGIN_EVENT_NAME,\n LOGOUT_EVENT_NAME,\n NOT_LOGIN_ERR_MSG,\n ERROR_PROP_NAME\n} from 'jsonql-constants'\n\nimport { getDebug, createEvt, clearMainEmitEvt } from './utils'\nimport triggerNamespacesOnError from './utils/trigger-namespaces-on-error'\nconst debugFn = getDebug('client-event-handler')\n\n/**\n * A fake ee handler\n * @param {string} namespace nsp\n * @param {object} ee EventEmitter\n * @return {void}\n */\nconst notLoginWsHandler = (namespace, ee) => {\n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function(resolverName, args) {\n debugFn('noLoginHandler hijack the ws call', namespace, resolverName, args)\n let error = {\n message: NOT_LOGIN_ERR_MSG\n }\n // It should just throw error here and should not call the result\n // because that's channel for handling normal event not the fake one\n ee.$call(createEvt(namespace, resolverName, ERROR_PROP_NAME), [error])\n // also trigger the result handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, RESULT_PROP_NAME), [{ error }])\n }\n )\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {array} namespaces namespace(s)\n * @param {object} ee Event Emitter instance\n * @param {function} bindWsHandler binding the ee to ws\n * @param {array} namespaces array of namespace available\n * @param {object} nsps namespaced nsp\n * @return {void} nothing\n */\nexport default function clientEventHandler(opts, nspMap, ee, bindWsHandler, namespaces, nsps) {\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run a waterfall here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n if (nsps[namespace]) {\n debugFn('call bindWsHandler', namespace)\n let args = [namespace, nsps[namespace], ee]\n if (opts.serverType === SOCKET_IO) {\n let { nspSet } = nspMap;\n args.push(nspSet[namespace])\n args.push(opts)\n }\n Reflect.apply(bindWsHandler, null, args)\n } else {\n // a dummy placeholder\n notLoginWsHandler(namespace, ee)\n }\n })\n // this will be available regardless enableAuth\n // because the server can log the client out\n ee.$on(LOGOUT_EVENT_NAME, function() {\n debugFn('LOGOUT_EVENT_NAME')\n // disconnect(nsps, opts.serverType)\n // we need to issue error to all the namespace onError handler\n triggerNamespacesOnError(ee, namespaces, LOGOUT_EVENT_NAME)\n // rebind all of the handler to the fake one\n namespaces.forEach( namespace => {\n clearMainEmitEvt(ee, namespace)\n // clear out the nsp\n nsps[namespace] = false;\n // add a NOT LOGIN error if call\n notLoginWsHandler(namespace, ee)\n })\n })\n}\n","// take the ws reply data for use\nimport { WS_EVT_NAME, WS_DATA_NAME, WS_REPLY_TYPE } from 'jsonql-constants'\nimport { isString, isKeyInObject } from 'jsonql-params-validator'\nimport { JsonqlError, clientErrorsHandler } from 'jsonql-errors'\n\nimport getDebug from '../utils/get-debug'\nconst debugFn = getDebug('extract-ws-payload')\n\nconst keys = [ WS_REPLY_TYPE, WS_EVT_NAME, WS_DATA_NAME ]\n\n/**\n * @param {object} payload should be string when reply but could be transformed\n * @return {boolean} true is OK\n */\nconst isWsReply = payload => {\n const { data } = payload;\n if (data) {\n let result = keys.filter(key => isKeyInObject(data, key))\n return (result.length === keys.length) ? data : false;\n }\n return false;\n}\n\n/**\n * @param {object} payload This is the entire ws Event Object\n * @return {object} false on failed\n */\nconst extractWsPayload = payload => {\n const { data } = payload;\n let json = isString(data) ? JSON.parse(data) : data;\n // debugFn('extractWsPayload', json)\n let fdata;\n if ((fdata = isWsReply(json)) !== false) {\n return {\n resolverName: fdata[WS_EVT_NAME],\n data: fdata[WS_DATA_NAME],\n type: fdata[WS_REPLY_TYPE]\n };\n }\n throw new JsonqlError('payload can not be decoded', payload)\n}\n// export it\nexport default extractWsPayload\n","// the WebSocket main handler\nimport {\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME,\n EMIT_EVT\n} from '../utils/constants'\nimport {\n ERROR_PROP_NAME,\n LOGIN_EVENT_NAME,\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_TYPE,\n READY_PROP_NAME\n} from 'jsonql-constants'\n\nimport extractWsPayload from './extract-ws-payload'\nimport { createQueryStr } from 'jsonql-params-validator'\n\nimport { getDebug, createEvt } from '../utils'\nconst debugFn = getDebug('ws-main-handler')\n\n/**\n * under extremely circumstances we might not even have a resolverName, then\n * we issue a global error for the developer to catch it\n * @param {object} ee event emitter\n * @param {string} namespace nsp\n * @param {string} resolverName resolver\n * @param {object} json decoded payload or error object\n */\nconst errorTypeHandler = (ee, namespace, resolverName, json) => {\n let evt = [namespace]\n if (resolverName) {\n debugFn(`a global error on ${namespace}`)\n evt.push(resolverName)\n }\n evt.push(ERROR_PROP_NAME)\n let evtName = Reflect.apply(createEvt, null, evt)\n // test if there is a data field\n let payload = json.data || json;\n ee.$trigger(evtName, [payload])\n}\n\n/**\n * Binding the even to socket normally\n * @param {string} namespace\n * @param {object} ws the nsp\n * @param {object} ee EventEmitter\n * @return {object} promise resolve after the onopen event\n */\nexport default function wsMainHandlerAction(namespace, ws, ee) {\n // send\n ws.onopen = function() {\n // we just call the onReady\n ee.$call(READY_PROP_NAME, namespace)\n // add listener\n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function(resolverName, args) {\n debugFn('calling server', resolverName, args)\n ws.send(\n createQueryStr(resolverName, args)\n )\n }\n )\n }\n\n // reply\n ws.onmessage = function(payload) {\n try {\n const json = extractWsPayload(payload)\n debugFn('Hear from server', json)\n const { resolverName, type } = json;\n switch (type) {\n case EMIT_REPLY_TYPE:\n let r = ee.$trigger(createEvt(namespace, resolverName, MESSAGE_PROP_NAME), [json])\n debugFn(MESSAGE_PROP_NAME, r)\n break;\n case ACKNOWLEDGE_REPLY_TYPE:\n debugFn(RESULT_PROP_NAME, json)\n let x = ee.$trigger(createEvt(namespace, resolverName, RESULT_PROP_NAME), [json])\n debugFn('onResult add to event?', x)\n break;\n case ERROR_TYPE:\n // this is handled error and we won't throw it\n // we need to extract the error from json\n errorTypeHandler(ee, namespace, resolverName, json)\n break;\n // @TODO there should be an error type instead of roll into the other two types? TBC\n default:\n // if this happen then we should throw it and halt the operation all together\n debugFn('Unhandled event!', json)\n errorTypeHandler(ee, namespace, resolverName, json)\n // let error = {error: {'message': 'Unhandled event!', type}};\n // ee.$trigger(createEvt(namespace, resolverName, RESULT_PROP_NAME), [error])\n }\n } catch(e) {\n errorTypeHandler(ee, namespace, false, e)\n }\n }\n // when the server close the connection\n ws.onclose = function() {\n debugFn('ws.onclose')\n // @TODO what to do with this\n // ee.$trigger(LOGOUT_EVENT_NAME, [namespace])\n }\n // listen to the LOGOUT_EVENT_NAME\n ee.$on(LOGOUT_EVENT_NAME, function close() {\n try {\n debugFn('terminate ws connection')\n ws.terminate()\n } catch(e) {\n debugFn('terminate ws error', e)\n }\n })\n}\n","// make this another standalone module\nimport { getNameFromPayload } from 'jsonql-params-validator'\nimport { LOGIN_EVENT_NAME, LOGOUT_EVENT_NAME, JS_WS_NAME } from 'jsonql-constants'\nimport { nspClient, nspAuthClient } from '../utils/create-nsp-client'\n// this become the cb\nimport clientEventHandler from '../client-event-handler'\nimport triggerNamespacesOnError from '../utils/trigger-namespaces-on-error'\n// move this up one level from client-event-handler\nimport wsMainHandler from './ws-main-handler'\nimport { getDebug, clearMainEmitEvt, getNamespaceInOrder, disconnect } from '../utils'\nconst debugFn = getDebug('ws-create-client')\n\n/**\n * Because the nsps can be throw away so it doesn't matter the scope\n * this will get reuse again\n * @param {object} opts configuration\n * @param {object} nspMap from contract\n * @param {string|null} token whether we have the token at run time\n * @return {object} nsps namespace with namespace as key\n */\nconst createNsps = function(opts, nspMap, token) {\n let { nspSet, publicNamespace } = nspMap;\n let login = false;\n let namespaces = [];\n let nsps = {};\n // first we need to binding all the events handler\n if (opts.enableAuth && opts.useJwt) {\n login = true; // just saying we need to listen to login event\n namespaces = getNamespaceInOrder(nspSet, publicNamespace)\n nsps = namespaces.map((namespace, i) => {\n if (i === 0) {\n if (token) {\n opts.token = token;\n return {[namespace]: nspAuthClient(namespace, opts)}\n }\n return {[namespace]: false}\n }\n return {[namespace]: nspClient(namespace, opts)}\n }).reduce((first, next) => Object.assign(first, next), {})\n } else {\n let namespace = getNameFromPayload(nspSet)\n namespaces.push(namespace)\n // standard without login\n // the stock version should not have a namespace\n nsps[namespace] = nspClient(false, opts)\n }\n // return\n return { nsps, namespaces, login }\n}\n\n/**\n * create a ws client\n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nexport default function createClient(opts, nspMap, ee) {\n // arguments that don't change\n let args = [opts, nspMap, ee, wsMainHandler]\n // now create the nsps\n let { nsps, namespaces, login } = createNsps(opts, nspMap, opts.token)\n // binding the listeners - and it will listen to LOGOUT event\n // to unbind itself, and the above call will bind it again\n Reflect.apply(clientEventHandler, null, args.concat([namespaces, nsps]))\n // setup listener\n if (login) {\n ee.$only(LOGIN_EVENT_NAME, function(token) {\n disconnect(nsps, JS_WS_NAME)\n // @TODO should we trigger error on this one?\n // triggerNamespacesOnError(ee, namespaces, LOGIN_EVENT_NAME)\n clearMainEmitEvt(ee, namespaces)\n debugFn('LOGIN_EVENT_NAME', token)\n let newNsps = createNsps(opts, nspMap, token)\n // rebind it\n Reflect.apply(\n clientEventHandler,\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\n }\n // return what input\n return { opts, nspMap, ee }\n}\n","// we only need to export one interface from now on\n\nimport createClient from './create-client'\n\nexport default createClient\n","// this will create the socket.io client\nimport { chainPromises } from 'jsonql-jwt'\nimport { getNameFromPayload, isString } from 'jsonql-params-validator'\nimport { LOGIN_EVENT_NAME, LOGOUT_EVENT_NAME } from 'jsonql-constants'\n\nimport { nspClient, nspAuthClient } from '../utils/create-nsp-client'\nimport clientEventHandler from '../client-event-handler'\nimport ioMainHandler from './io-main-handler'\n\nimport { getDebug, clearMainEmitEvt, getNamespaceInOrder, disconnect } from '../utils'\nconst debugFn = getDebug('io-create-client')\n\n// just to make it less ugly\nconst mapNsps = (nsps, namespaces) => nsps\n .map((nsp, i) => ({[namespaces[i]]: nsp}))\n .reduce((last, next) => Object.assign(last,next), {})\n\n/**\n * This one will run the create nsps in sequence and make sure\n * the auth one connect before we call the others\n * @param {object} opts configuration\n * @param {object} nspMap contract map\n * @param {string} token validation\n * @return {object} promise resolve with namespaces, nsps in same order array\n */\nconst createAuthNsps = function(opts, nspMap, token, namespaces) {\n let { publicNamespace } = nspMap;\n opts.token = token;\n let p1 = () => nspAuthClient(namespaces[0], opts)\n let p2 = () => nspClient(namespaces[1], opts)\n return chainPromises([p1(), p2()])\n .then(nsps => ({\n nsps: mapNsps(nsps, namespaces),\n namespaces,\n login: false\n }))\n}\n\n/**\n * Because the nsps can be throw away so it doesn't matter the scope\n * this will get reuse again\n * @param {object} opts configuration\n * @param {object} nspMap from contract\n * @param {string|null} token whether we have the token at run time\n * @return {object} nsps namespace with namespace as key\n */\nconst createNsps = function(opts, nspMap, token) {\n let { nspSet, publicNamespace } = nspMap;\n let login = false;\n let nsps = {}\n // first we need to binding all the events handler\n if (opts.enableAuth && opts.useJwt) {\n let namespaces = getNamespaceInOrder(nspSet, publicNamespace)\n debugFn('namespaces', namespaces)\n login = opts.useJwt; // just saying we need to listen to login event\n if (token) {\n debugFn('call createAuthNsps')\n return createAuthNsps(opts, nspMap, token, namespaces)\n }\n debugFn('init with a placeholder')\n return nspClient(publicNamespace, opts)\n .then(nsp => ({\n nsps: {\n [ publicNamespace ]: nsp,\n [ namespaces[0] ]: false\n },\n namespaces,\n login\n }))\n }\n // standard without login\n // the stock version should not have a namespace\n return nspClient(false, opts)\n .then(nsp => ({\n nsps: {[publicNamespace]: nsp},\n namespaces: [publicNamespace],\n login\n }))\n}\n\n\n\n/**\n * This is just copy of the ws version we need to figure\n * out how to deal with the roundtrip login later\n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nexport default function createClient(opts, nspMap, ee) {\n // arguments don't change\n let args = [opts, nspMap, ee, ioMainHandler]\n return createNsps(opts, nspMap, opts.token)\n .then( ({ nsps, namespaces, login }) => {\n // binding the listeners - and it will listen to LOGOUT event\n // to unbind itself, and the above call will bind it again\n Reflect.apply(clientEventHandler, null, args.concat([namespaces, nsps]))\n if (login) {\n ee.$only(LOGIN_EVENT_NAME, function(token) {\n // here we should disconnect all the previous nsps\n disconnect(nsps)\n // first trigger a LOGOUT event to unbind ee to ws\n // ee.$trigger(LOGOUT_EVENT_NAME) // <-- this seems to cause a lot of problems\n clearMainEmitEvt(ee, namespaces)\n debugFn('LOGIN_EVENT_NAME')\n createNsps(opts, nspMap, token)\n .then(newNsps => {\n // rebind it\n Reflect.apply(\n clientEventHandler,\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\n })\n }\n // return this will also works because the outter call are in promise chain\n return { opts, nspMap, ee }\n })\n}\n","// generator resolvers\n// this will be a mini client server architect\n// The reason is when the enableAuth setup - the private route\n// might not be validated, but we need the callable point is ready\n// therefore this part will always take the contract and generate\n// callable api for the developer to setup their front end\n// the only thing is - when they call they might get an error or\n// NOT_LOGIN_IN and they can react to this error accordingly\nimport {\n JsonqlResolverNotFoundError,\n JsonqlValidationError,\n JsonqlError,\n finalCatch\n} from 'jsonql-errors'\nimport {\n validateAsync,\n validateSync,\n isKeyInObject,\n isString\n} from 'jsonql-params-validator'\nimport {\n ERROR_TYPE,\n DATA_KEY,\n ERROR_KEY,\n ERROR_PROP_NAME,\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME,\n SEND_MSG_PROP_NAME,\n LOGIN_EVENT_NAME,\n READY_PROP_NAME,\n LOGOUT_EVENT_NAME\n} from 'jsonql-constants'\nimport { getDebug, constants, createEvt, toArray } from './utils'\nconst { EMIT_EVT, NOT_ALLOW_OP, UNKNOWN_RESULT, MY_NAMESPACE } = constants;\nconst debugFn = getDebug('generator')\n\n/**\n * prepare the methods\n * @param {object} opts configuration\n * @param {object} nspMap resolvers index by their namespace\n * @param {object} ee EventEmitter\n * @return {object} of resolvers\n * @public\n */\nexport default function generator(opts, nspMap, ee) {\n const obj = {};\n const { nspSet } = nspMap;\n for (let namespace in nspSet) {\n let list = nspSet[namespace]\n for (let resolverName in list) {\n let params = list[resolverName]\n let fn = createResolver(ee, namespace, resolverName, params)\n obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n }\n }\n // add error handler\n createNamespaceErrorHandler(obj, ee, nspSet)\n // add onReady handler\n createOnReadyhandler(obj, ee, nspSet)\n // Auth related methods\n createAuthMethods(obj, ee, opts)\n // this is a helper method for the developer to know the namespace inside\n obj.getNsp = () => {\n return Object.keys(nspSet)\n }\n // output\n return obj;\n}\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @return {function} resolver\n */\nfunction createResolver(ee, namespace, resolverName, params) {\n // note we pass the new withResult=true option\n return function(...args) {\n return validateAsync(args, params.params, true)\n .then( _args => actionCall(ee, namespace, resolverName, _args) )\n .catch(finalCatch)\n }\n}\n\n/**\n * just wrapper\n * @param {object} ee EventEmitter\n * @param {string} namespace where this belongs\n * @param {string} resolverName resolver\n * @param {array} args arguments\n * @return {void} nothing\n */\nfunction actionCall(ee, namespace, resolverName, args = []) {\n debugFn(`actionCall: ${namespace} ${resolverName}`, args)\n ee.$trigger(createEvt(namespace, EMIT_EVT), [\n resolverName,\n toArray(args)\n ])\n}\n\n/**\n * break out to use in different places to handle the return from server\n * @param {object} data from server\n * @param {function} resolver from promise\n * @param {function} rejecter from promise\n * @return {void} nothing\n */\nfunction respondHandler(data, resolver, rejecter) {\n if (isKeyInObject(data, 'error')) {\n debugFn('rejecter called', data.error)\n rejecter(data.error)\n } else if (isKeyInObject(data, 'data')) {\n debugFn('resolver called', data.data)\n resolver(data.data)\n } else {\n debugFn('UNKNOWN_RESULT', data)\n rejecter({message: UNKNOWN_RESULT, error: data})\n }\n}\n\n/**\n * Add extra property to the resolver\n * @param {string} namespace where this belongs\n * @param {string} resolverName name as event name\n * @param {object} params from contract\n * @param {function} fn resolver function\n * @param {object} ee EventEmitter\n * @return {function} resolver\n */\nconst setupResolver = (namespace, resolverName, params, fn, ee) => {\n // also need to setup a getter to get back the namespace of this resolver\n if (Object.getOwnPropertyDescriptor(fn, MY_NAMESPACE) === undefined) {\n Object.defineProperty(fn, MY_NAMESPACE, {\n value: namespace,\n writeable: false\n })\n }\n // onResult handler\n if (Object.getOwnPropertyDescriptor(fn, RESULT_PROP_NAME) === undefined) {\n Object.defineProperty(fn, RESULT_PROP_NAME, {\n set: function(resultCallback) {\n if (typeof resultCallback === 'function') {\n ee.$only(\n createEvt(namespace, resolverName, RESULT_PROP_NAME),\n function resultHandler(result) {\n respondHandler(result, resultCallback, (error) => {\n ee.$trigger(createEvt(namespace, resolverName, ERROR_PROP_NAME), error)\n })\n }\n )\n }\n },\n get: function() {\n return null;\n }\n })\n }\n // we do need to add the send prop back because it's the only way to deal with\n // bi-directional data stream\n if (Object.getOwnPropertyDescriptor(fn, MESSAGE_PROP_NAME) === undefined) {\n Object.defineProperty(fn, MESSAGE_PROP_NAME, {\n set: function(messageCallback) {\n // we expect this to be a function\n if (typeof messageCallback === 'function') {\n // did that add to the callback\n let onMessageCallback = (args) => {\n respondHandler(args, messageCallback, (error) => {\n ee.$trigger(createEvt(namespace, resolverName, ERROR_PROP_NAME), error)\n })\n }\n // register the handler for this message event\n ee.$only(createEvt(namespace, resolverName, MESSAGE_PROP_NAME), onMessageCallback)\n }\n },\n get: function() {\n return null; // just return nothing\n }\n })\n }\n // add an ERROR_PROP_NAME handler\n if (Object.getOwnPropertyDescriptor(fn, ERROR_PROP_NAME) === undefined) {\n Object.defineProperty(fn, ERROR_PROP_NAME, {\n set: function(resolverErrorHandler) {\n if (typeof resolverErrorHandler === 'function') {\n // please note ERROR_PROP_NAME can add multiple listners\n ee.$only(createEvt(namespace, resolverName, ERROR_PROP_NAME), resolverErrorHandler)\n }\n },\n get: function() {\n return null;\n }\n })\n }\n // pairing with the server vesrion SEND_MSG_PROP_NAME\n if (Object.getOwnPropertyDescriptor(fn, SEND_MSG_PROP_NAME) === undefined) {\n Object.defineProperty(fn, SEND_MSG_PROP_NAME, {\n set: function(messagePayload) {\n const result = validateSync(toArray(messagePayload), params.params, true)\n // here is the different we don't throw erro instead we trigger an\n // onError\n if (result[ERROR_KEY] && result[ERROR_KEY].length) {\n ee.$call(\n createEvt(namespace, resolverName, ERROR_PROP_NAME),\n [JsonqlValidationError(resolverName, result[ERROR_KEY])]\n )\n } else {\n // there is no return only an action call\n actionCall(ee, namespace, resolverName, result[DATA_KEY])\n }\n },\n get: function() {\n return null; // just return nothing\n }\n })\n }\n return fn;\n}\n\n/**\n * The problem is the namespace can have more than one\n * and we only have on onError message\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @param {object} nspSet namespace keys\n * @return {void}\n */\nconst createNamespaceErrorHandler = (obj, ee, nspSet) => {\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the obj itself\n if (Object.getOwnPropertyDescriptor(obj, ERROR_PROP_NAME) === undefined) {\n Object.defineProperty(obj, ERROR_PROP_NAME, {\n set: function(namespaceErrorHandler) {\n if (typeof namespaceErrorHandler === 'function') {\n // please note ERROR_PROP_NAME can add multiple listners\n for (let namespace in nspSet) {\n // this one is very tricky, we need to make sure the trigger is calling\n // with the namespace as well as the error\n ee.$on(createEvt(namespace, ERROR_PROP_NAME), namespaceErrorHandler)\n }\n }\n },\n get: function() {\n return null;\n }\n })\n }\n}\n\n/**\n * This event will fire when the socket.io.on('connection') and ws.onopen\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @param {object} nspSet namespace keys\n * @return {void}\n */\nconst createOnReadyhandler = (obj, ee, nspSet) => {\n if (Object.getOwnPropertyDescriptor(obj, READY_PROP_NAME) === undefined) {\n Object.defineProperty(obj, READY_PROP_NAME, {\n set: function(onReadyCallback) {\n if (typeof onReadyCallback === 'function') {\n // reduce it down to just one flat level\n let result = ee.$on(READY_PROP_NAME, onReadyCallback)\n }\n },\n get: function() {\n return null;\n }\n })\n }\n}\n\n/**\n * Create auth related methods\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @param {object} opts configuration\n * @return {void}\n */\nconst createAuthMethods = (obj, ee, opts) => {\n if (opts.enableAuth) {\n // create an additonal login handler\n // we require the token\n obj[opts.loginHandlerName] = (token) => {\n debugFn(opts.loginHandlerName, token)\n if (token && isString(token)) {\n return ee.$trigger(LOGIN_EVENT_NAME, [token])\n }\n throw new JsonqlValidationError(opts.loginHandlerName)\n }\n // logout event handler\n obj[opts.logoutHandlerName] = (...args) => {\n ee.$trigger(LOGOUT_EVENT_NAME, args)\n }\n }\n}\n","// main api to get the ws-client\n\nimport createSocketClient from './create-socket-client'\nimport generator from './generator'\n\nimport { checkOptions, ee, processContract } from './utils'\n\n/**\n * The main interface to create the wsClient for use\n * @param {function} clientGenerator this is an internal way to generate node or browser client\n * @return {function} wsClient\n * @public\n */\nexport default function main(clientGenerator) {\n /**\n * @param {object} config configuration\n * @param {object} [eventEmitter=false] this will be the bridge between clients\n * @return {object} wsClient\n */\n const wsClient = (config, eventEmitter = false) => {\n return checkOptions(config)\n .then(opts => ({\n opts,\n nspMap: processContract(opts),\n ee: eventEmitter || new ee()\n })\n )\n .then(clientGenerator)\n .then(\n ({ opts, nspMap, ee }) => createSocketClient(opts, nspMap, ee)\n )\n .then(\n ({ opts, nspMap, ee }) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error('jsonql-ws-client init error', err)\n })\n }\n // use the Object.addProperty trick\n Object.defineProperty(wsClient, 'CLIENT_TYPE_INFO', {\n value: '__PLACEHOLDER__',\n writable: false\n })\n return wsClient;\n}\n","// This is the module entry point\nimport clientGenerator from './src/utils/client-generator'\nimport main from './src/main'\n\nexport default main(clientGenerator)\n"],"names":[],"mappings":";;;;;;;;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;ECAA;;;;;;;;;;;ECAA;;;;;;;;;ECAA;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;"} \ No newline at end of file +{"version":3,"file":"jsonql-ws-client.js","sources":["../node_modules/jsonql-jwt/src/client/socketio/socket-io-client.js","../node_modules/jsonql-jwt/src/client/socketio/handshake-login.js","../node_modules/jsonql-errors/src/500-error.js","../node_modules/jsonql-errors/src/enum-error.js","../node_modules/jsonql-errors/src/type-error.js","../node_modules/jsonql-errors/src/checker-error.js","../node_modules/jsonql-errors/src/validation-error.js","../node_modules/jsonql-errors/src/server-error.js","../node_modules/jsonql-jwt/src/client/socketio/roundtrip-login.js","../node_modules/rollup-plugin-node-globals/src/global.js","../node_modules/lodash-es/_objectToString.js","../node_modules/lodash-es/isObjectLike.js","../node_modules/lodash-es/_arrayMap.js","../node_modules/lodash-es/isArray.js","../node_modules/lodash-es/isObject.js","../node_modules/lodash-es/identity.js","../node_modules/lodash-es/_toSource.js","../node_modules/lodash-es/_getValue.js","../node_modules/lodash-es/_apply.js","../node_modules/lodash-es/_copyArray.js","../node_modules/lodash-es/_shortOut.js","../node_modules/lodash-es/constant.js","../node_modules/lodash-es/_baseFindIndex.js","../node_modules/lodash-es/_baseIsNaN.js","../node_modules/lodash-es/_strictIndexOf.js","../node_modules/lodash-es/_isIndex.js","../node_modules/lodash-es/eq.js","../node_modules/lodash-es/isLength.js","../node_modules/lodash-es/_isPrototype.js","../node_modules/lodash-es/_baseTimes.js","../node_modules/lodash-es/stubFalse.js","../node_modules/lodash-es/_baseUnary.js","../node_modules/lodash-es/_overArg.js","../node_modules/lodash-es/_nativeKeysIn.js","../node_modules/lodash-es/_hashDelete.js","../node_modules/lodash-es/_listCacheClear.js","../node_modules/lodash-es/_isKeyable.js","../node_modules/lodash-es/_arrayPush.js","../node_modules/lodash-es/_baseSlice.js","../node_modules/lodash-es/_hasUnicode.js","../node_modules/lodash-es/_asciiToArray.js","../node_modules/lodash-es/_unicodeToArray.js","../node_modules/lodash-es/_stackDelete.js","../node_modules/lodash-es/_stackGet.js","../node_modules/lodash-es/_stackHas.js","../node_modules/lodash-es/_arrayFilter.js","../node_modules/lodash-es/stubArray.js","../node_modules/lodash-es/_setCacheAdd.js","../node_modules/lodash-es/_setCacheHas.js","../node_modules/lodash-es/_arraySome.js","../node_modules/lodash-es/_cacheHas.js","../node_modules/lodash-es/_mapToArray.js","../node_modules/lodash-es/_setToArray.js","../node_modules/lodash-es/_matchesStrictComparable.js","../node_modules/lodash-es/_baseHasIn.js","../node_modules/lodash-es/_baseProperty.js","../node_modules/lodash-es/_createBaseFor.js","../node_modules/lodash-es/_safeGet.js","../node_modules/lodash-es/_baseFindKey.js","../node_modules/lodash-es/isNull.js","../node_modules/lodash-es/isUndefined.js","../node_modules/lodash-es/negate.js","../node_modules/jsonql-params-validator/src/not-empty.js","../node_modules/jsonql-params-validator/src/number.js","../node_modules/jsonql-params-validator/src/string.js","../node_modules/jsonql-params-validator/src/boolean.js","../node_modules/jsonql-params-validator/src/any.js","../node_modules/jsonql-params-validator/src/constants.js","../node_modules/jsonql-params-validator/src/combine.js","../node_modules/jsonql-params-validator/src/array.js","../node_modules/jsonql-params-validator/src/object.js","../node_modules/jsonql-params-validator/src/validator.js","../node_modules/jsonql-params-validator/src/is-in-array.js","../node_modules/jsonql-params-validator/src/options/run-validation.js","../node_modules/jsonql-params-validator/src/options/check-options-async.js","../node_modules/jsonql-params-validator/src/options/construct-config.js","../node_modules/jsonql-params-validator/src/options/index.js","../node_modules/jsonql-params-validator/src/check-is-contract.js","../node_modules/jsonql-params-validator/src/params-api.js","../node_modules/jsonql-params-validator/index.js","../node_modules/jsonql-jwt/src/client/utils/group-by-namespace.js","../node_modules/jsonql-jwt/src/client/utils/chain-promises.js","../node_modules/jwt-decode/lib/atob.js","../node_modules/jsonql-jwt/src/client/ws/ws.js","../src/utils/constants.js","../src/utils/client-generator.js","../src/utils/create-nsp-client.js","../node_modules/nb-event-service/src/hash-code.js","../node_modules/nb-event-service/src/suspend.js","../node_modules/nb-event-service/src/store-service.js","../node_modules/nb-event-service/src/event-service.js","../node_modules/nb-event-service/index.js","../src/utils/process-contract.js","../src/utils/index.js","../src/client-event-handler.js","../src/ws/extract-ws-payload.js","../src/ws/ws-main-handler.js","../src/ws/create-client.js","../src/ws/index.js","../src/io/create-client.js","../src/generator.js","../src/main.js","../index.js"],"sourcesContent":["// this should work on browser as well as node\n// import io from 'socket.io-cilent'\n\n/**\n * Create a normal client\n * @param {object} io socket io instance\n * @param {string} url end point\n * @param {object} [options={}] configuration\n * @return {object} nsp instance\n */\nexport default function socketIoClient(io, url, options = {}) {\n return io.connect(url, options)\n}\n","// handshake login\nimport { TOKEN_PARAM_NAME, DEFAULT_WS_WAIT_TIME } from 'jsonql-constants';\nimport socketIoClient from './socket-io-client'\n\n/**\n * Create a async version to match up the rest of the api\n * @param {object} io socket io instance\n * @param {string} url end point\n * @param {object} [options={}] configuration\n * @return {object} Promise resolve to nsp instance\n */\nexport function socketIoClientAsync(...args) {\n return Promise.resolve(\n Reflect.apply(socketIoClient, null, args)\n )\n}\n\n/**\n * Login during handshake\n * @param {object} io the new socket.io instance\n * @param {string} token to send\n * @param {object} [options = {}] extra options\n * @return {object} the io object itself\n */\nexport function socketIoHandshakeLogin(io, url, token, options = {}) {\n const wait = options.timeout || DEFAULT_WS_WAIT_TIME;\n const config = Object.assign({}, options, {\n query: [TOKEN_PARAM_NAME, token].join('=')\n })\n let timer;\n const nsp = socketIoClient(io, url, config)\n return new Promise((resolver, rejecter) => {\n timer = setTimeout(() => {\n rejecter()\n }, wait)\n nsp.on('connect', () => {\n console.info('socketIoHandshakeLogin connected')\n resolver(nsp)\n clearTimeout(timer)\n })\n })\n}\n","/**\n * This is a custom error to throw when server throw a 500\n * This help us to capture the right error, due to the call happens in sequence\n * @param {string} message to tell what happen\n * @param {mixed} extra things we want to add, 500?\n */\nexport default class Jsonql500Error extends Error {\n constructor(...args) {\n super(...args);\n\n this.message = args[0];\n this.detail = args[1];\n\n this.className = Jsonql500Error.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, Jsonql500Error);\n }\n }\n\n static get statusCode() {\n return 500;\n }\n\n static get name() {\n return 'Jsonql500Error';\n }\n\n}\n","// this get throw from within the checkOptions when run through the enum failed\nexport default class JsonqlEnumError extends Error {\n constructor(...args) {\n super(...args);\n \n this.message = args[0];\n this.detail = args[1];\n\n this.className = JsonqlEnumError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlEnumError);\n }\n }\n\n static get name() {\n return 'JsonqlEnumError';\n }\n}\n","// this will throw from inside the checkOptions\nexport default class JsonqlTypeError extends Error {\n constructor(...args) {\n super(...args);\n\n this.message = args[0];\n this.detail = args[1];\n\n this.className = JsonqlTypeError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlTypeError);\n }\n }\n\n static get name() {\n return 'JsonqlTypeError';\n }\n}\n","// allow supply a custom checker function\n// if that failed then we throw this error\nexport default class JsonqlCheckerError extends Error {\n constructor(...args) {\n super(...args);\n this.message = args[0];\n this.detail = args[1];\n\n this.className = JsonqlCheckerError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlCheckerError);\n }\n }\n\n static get name() {\n return 'JsonqlCheckerError';\n }\n}\n","// custom validation error class\n// when validaton failed\nexport default class JsonqlValidationError extends Error {\n constructor(...args) {\n super(...args);\n\n this.message = args[0];\n this.detail = args[1];\n\n this.className = JsonqlValidationError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlValidationError);\n }\n }\n\n static get name() {\n return 'JsonqlValidationError';\n }\n}\n","// this is from an example from Koa team to use for internal middleware ctx.throw\n// but after the test the res.body part is unable to extract the required data\n// I keep this one here for future reference\n\nexport default class JsonqlServerError extends Error {\n\n constructor(statusCode, message) {\n super(message);\n this.statusCode = statusCode;\n this.className = JsonqlServerError.name;\n }\n\n static get name() {\n return 'JsonqlServerError';\n }\n}\n","// import { isString } from 'jsonql-params-validator';\nimport { JsonqlValidationError } from 'jsonql-errors';\nimport socketIoClient from './socket-io-client'\n/**\n * The core method of the socketJwt client side\n * @param {object} socket the socket.io connected instance\n * @param {string} token for validation\n * @param {function} onAuthenitcated callback when authenticated\n * @param {function} onUnauthorized callback when authorized\n * @return {void}\n */\nconst socketIoLoginAction = (socket, token, onAuthenticated, onUnauthorized) => {\n socket\n .emit('authenticate', { token })\n .on('authenticated', onAuthenticated)\n .on('unauthorized', onUnauthorized)\n}\n\n/**\n * completely rethink about how the browser version should be!\n *\n */\nexport default function socketIoRoundtripLogin(io, url, token, options = {}) {\n const socket = socketIoClient(io, url)\n return new Promise((resolver, rejecter) => {\n socketIoLoginAction(socket, token, () => resolver(socket) , rejecter);\n })\n}\n","export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nexport default isObject;\n","/**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\nfunction identity(value) {\n return value;\n}\n\nexport default identity;\n","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n}\n\nexport default toSource;\n","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n return object == null ? undefined : object[key];\n}\n\nexport default getValue;\n","/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\nexport default apply;\n","/**\n * Copies the values of `source` to `array`.\n *\n * @private\n * @param {Array} source The array to copy values from.\n * @param {Array} [array=[]] The array to copy values to.\n * @returns {Array} Returns `array`.\n */\nfunction copyArray(source, array) {\n var index = -1,\n length = source.length;\n\n array || (array = Array(length));\n while (++index < length) {\n array[index] = source[index];\n }\n return array;\n}\n\nexport default copyArray;\n","/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n}\n\nexport default shortOut;\n","/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n return function() {\n return value;\n };\n}\n\nexport default constant;\n","/**\n * The base implementation of `_.findIndex` and `_.findLastIndex` without\n * support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} predicate The function invoked per iteration.\n * @param {number} fromIndex The index to search from.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseFindIndex(array, predicate, fromIndex, fromRight) {\n var length = array.length,\n index = fromIndex + (fromRight ? 1 : -1);\n\n while ((fromRight ? index-- : ++index < length)) {\n if (predicate(array[index], index, array)) {\n return index;\n }\n }\n return -1;\n}\n\nexport default baseFindIndex;\n","/**\n * The base implementation of `_.isNaN` without support for number objects.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.\n */\nfunction baseIsNaN(value) {\n return value !== value;\n}\n\nexport default baseIsNaN;\n","/**\n * A specialized version of `_.indexOf` which performs strict equality\n * comparisons of values, i.e. `===`.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction strictIndexOf(array, value, fromIndex) {\n var index = fromIndex - 1,\n length = array.length;\n\n while (++index < length) {\n if (array[index] === value) {\n return index;\n }\n }\n return -1;\n}\n\nexport default strictIndexOf;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n var type = typeof value;\n length = length == null ? MAX_SAFE_INTEGER : length;\n\n return !!length &&\n (type == 'number' ||\n (type != 'symbol' && reIsUint.test(value))) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\nexport default isIndex;\n","/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n return value === other || (value !== value && other !== other);\n}\n\nexport default eq;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\nexport default isLength;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n}\n\nexport default isPrototype;\n","/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\nexport default baseTimes;\n","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n return false;\n}\n\nexport default stubFalse;\n","/**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\nfunction baseUnary(func) {\n return function(value) {\n return func(value);\n };\n}\n\nexport default baseUnary;\n","/**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\nfunction overArg(func, transform) {\n return function(arg) {\n return func(transform(arg));\n };\n}\n\nexport default overArg;\n","/**\n * This function is like\n * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * except that it includes inherited enumerable properties.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction nativeKeysIn(object) {\n var result = [];\n if (object != null) {\n for (var key in Object(object)) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default nativeKeysIn;\n","/**\n * Removes `key` and its value from the hash.\n *\n * @private\n * @name delete\n * @memberOf Hash\n * @param {Object} hash The hash to modify.\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction hashDelete(key) {\n var result = this.has(key) && delete this.__data__[key];\n this.size -= result ? 1 : 0;\n return result;\n}\n\nexport default hashDelete;\n","/**\n * Removes all key-value entries from the list cache.\n *\n * @private\n * @name clear\n * @memberOf ListCache\n */\nfunction listCacheClear() {\n this.__data__ = [];\n this.size = 0;\n}\n\nexport default listCacheClear;\n","/**\n * Checks if `value` is suitable for use as unique object key.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n */\nfunction isKeyable(value) {\n var type = typeof value;\n return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n ? (value !== '__proto__')\n : (value === null);\n}\n\nexport default isKeyable;\n","/**\n * Appends the elements of `values` to `array`.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to append.\n * @returns {Array} Returns `array`.\n */\nfunction arrayPush(array, values) {\n var index = -1,\n length = values.length,\n offset = array.length;\n\n while (++index < length) {\n array[offset + index] = values[index];\n }\n return array;\n}\n\nexport default arrayPush;\n","/**\n * The base implementation of `_.slice` without an iteratee call guard.\n *\n * @private\n * @param {Array} array The array to slice.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the slice of `array`.\n */\nfunction baseSlice(array, start, end) {\n var index = -1,\n length = array.length;\n\n if (start < 0) {\n start = -start > length ? 0 : (length + start);\n }\n end = end > length ? length : end;\n if (end < 0) {\n end += length;\n }\n length = start > end ? 0 : ((end - start) >>> 0);\n start >>>= 0;\n\n var result = Array(length);\n while (++index < length) {\n result[index] = array[index + start];\n }\n return result;\n}\n\nexport default baseSlice;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsVarRange = '\\\\ufe0e\\\\ufe0f';\n\n/** Used to compose unicode capture groups. */\nvar rsZWJ = '\\\\u200d';\n\n/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */\nvar reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');\n\n/**\n * Checks if `string` contains Unicode symbols.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {boolean} Returns `true` if a symbol is found, else `false`.\n */\nfunction hasUnicode(string) {\n return reHasUnicode.test(string);\n}\n\nexport default hasUnicode;\n","/**\n * Converts an ASCII `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction asciiToArray(string) {\n return string.split('');\n}\n\nexport default asciiToArray;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsVarRange = '\\\\ufe0e\\\\ufe0f';\n\n/** Used to compose unicode capture groups. */\nvar rsAstral = '[' + rsAstralRange + ']',\n rsCombo = '[' + rsComboRange + ']',\n rsFitz = '\\\\ud83c[\\\\udffb-\\\\udfff]',\n rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',\n rsNonAstral = '[^' + rsAstralRange + ']',\n rsRegional = '(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}',\n rsSurrPair = '[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]',\n rsZWJ = '\\\\u200d';\n\n/** Used to compose unicode regexes. */\nvar reOptMod = rsModifier + '?',\n rsOptVar = '[' + rsVarRange + ']?',\n rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',\n rsSeq = rsOptVar + reOptMod + rsOptJoin,\n rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';\n\n/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */\nvar reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');\n\n/**\n * Converts a Unicode `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction unicodeToArray(string) {\n return string.match(reUnicode) || [];\n}\n\nexport default unicodeToArray;\n","/**\n * Removes `key` and its value from the stack.\n *\n * @private\n * @name delete\n * @memberOf Stack\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction stackDelete(key) {\n var data = this.__data__,\n result = data['delete'](key);\n\n this.size = data.size;\n return result;\n}\n\nexport default stackDelete;\n","/**\n * Gets the stack value for `key`.\n *\n * @private\n * @name get\n * @memberOf Stack\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction stackGet(key) {\n return this.__data__.get(key);\n}\n\nexport default stackGet;\n","/**\n * Checks if a stack value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Stack\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction stackHas(key) {\n return this.__data__.has(key);\n}\n\nexport default stackHas;\n","/**\n * A specialized version of `_.filter` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\nfunction arrayFilter(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (predicate(value, index, array)) {\n result[resIndex++] = value;\n }\n }\n return result;\n}\n\nexport default arrayFilter;\n","/**\n * This method returns a new empty array.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {Array} Returns the new empty array.\n * @example\n *\n * var arrays = _.times(2, _.stubArray);\n *\n * console.log(arrays);\n * // => [[], []]\n *\n * console.log(arrays[0] === arrays[1]);\n * // => false\n */\nfunction stubArray() {\n return [];\n}\n\nexport default stubArray;\n","/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Adds `value` to the array cache.\n *\n * @private\n * @name add\n * @memberOf SetCache\n * @alias push\n * @param {*} value The value to cache.\n * @returns {Object} Returns the cache instance.\n */\nfunction setCacheAdd(value) {\n this.__data__.set(value, HASH_UNDEFINED);\n return this;\n}\n\nexport default setCacheAdd;\n","/**\n * Checks if `value` is in the array cache.\n *\n * @private\n * @name has\n * @memberOf SetCache\n * @param {*} value The value to search for.\n * @returns {number} Returns `true` if `value` is found, else `false`.\n */\nfunction setCacheHas(value) {\n return this.__data__.has(value);\n}\n\nexport default setCacheHas;\n","/**\n * A specialized version of `_.some` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n */\nfunction arraySome(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (predicate(array[index], index, array)) {\n return true;\n }\n }\n return false;\n}\n\nexport default arraySome;\n","/**\n * Checks if a `cache` value for `key` exists.\n *\n * @private\n * @param {Object} cache The cache to query.\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction cacheHas(cache, key) {\n return cache.has(key);\n}\n\nexport default cacheHas;\n","/**\n * Converts `map` to its key-value pairs.\n *\n * @private\n * @param {Object} map The map to convert.\n * @returns {Array} Returns the key-value pairs.\n */\nfunction mapToArray(map) {\n var index = -1,\n result = Array(map.size);\n\n map.forEach(function(value, key) {\n result[++index] = [key, value];\n });\n return result;\n}\n\nexport default mapToArray;\n","/**\n * Converts `set` to an array of its values.\n *\n * @private\n * @param {Object} set The set to convert.\n * @returns {Array} Returns the values.\n */\nfunction setToArray(set) {\n var index = -1,\n result = Array(set.size);\n\n set.forEach(function(value) {\n result[++index] = value;\n });\n return result;\n}\n\nexport default setToArray;\n","/**\n * A specialized version of `matchesProperty` for source values suitable\n * for strict equality comparisons, i.e. `===`.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @param {*} srcValue The value to match.\n * @returns {Function} Returns the new spec function.\n */\nfunction matchesStrictComparable(key, srcValue) {\n return function(object) {\n if (object == null) {\n return false;\n }\n return object[key] === srcValue &&\n (srcValue !== undefined || (key in Object(object)));\n };\n}\n\nexport default matchesStrictComparable;\n","/**\n * The base implementation of `_.hasIn` without support for deep paths.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {Array|string} key The key to check.\n * @returns {boolean} Returns `true` if `key` exists, else `false`.\n */\nfunction baseHasIn(object, key) {\n return object != null && key in Object(object);\n}\n\nexport default baseHasIn;\n","/**\n * The base implementation of `_.property` without support for deep paths.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @returns {Function} Returns the new accessor function.\n */\nfunction baseProperty(key) {\n return function(object) {\n return object == null ? undefined : object[key];\n };\n}\n\nexport default baseProperty;\n","/**\n * Creates a base function for methods like `_.forIn` and `_.forOwn`.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\nfunction createBaseFor(fromRight) {\n return function(object, iteratee, keysFunc) {\n var index = -1,\n iterable = Object(object),\n props = keysFunc(object),\n length = props.length;\n\n while (length--) {\n var key = props[fromRight ? length : ++index];\n if (iteratee(iterable[key], key, iterable) === false) {\n break;\n }\n }\n return object;\n };\n}\n\nexport default createBaseFor;\n","/**\n * Gets the value at `key`, unless `key` is \"__proto__\" or \"constructor\".\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction safeGet(object, key) {\n if (key === 'constructor' && typeof object[key] === 'function') {\n return;\n }\n\n if (key == '__proto__') {\n return;\n }\n\n return object[key];\n}\n\nexport default safeGet;\n","/**\n * The base implementation of methods like `_.findKey` and `_.findLastKey`,\n * without support for iteratee shorthands, which iterates over `collection`\n * using `eachFunc`.\n *\n * @private\n * @param {Array|Object} collection The collection to inspect.\n * @param {Function} predicate The function invoked per iteration.\n * @param {Function} eachFunc The function to iterate over `collection`.\n * @returns {*} Returns the found element or its key, else `undefined`.\n */\nfunction baseFindKey(collection, predicate, eachFunc) {\n var result;\n eachFunc(collection, function(value, key, collection) {\n if (predicate(value, key, collection)) {\n result = key;\n return false;\n }\n });\n return result;\n}\n\nexport default baseFindKey;\n","/**\n * Checks if `value` is `null`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `null`, else `false`.\n * @example\n *\n * _.isNull(null);\n * // => true\n *\n * _.isNull(void 0);\n * // => false\n */\nfunction isNull(value) {\n return value === null;\n}\n\nexport default isNull;\n","/**\n * Checks if `value` is `undefined`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.\n * @example\n *\n * _.isUndefined(void 0);\n * // => true\n *\n * _.isUndefined(null);\n * // => false\n */\nfunction isUndefined(value) {\n return value === undefined;\n}\n\nexport default isUndefined;\n","/** Error message constants. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/**\n * Creates a function that negates the result of the predicate `func`. The\n * `func` predicate is invoked with the `this` binding and arguments of the\n * created function.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Function\n * @param {Function} predicate The predicate to negate.\n * @returns {Function} Returns the new negated function.\n * @example\n *\n * function isEven(n) {\n * return n % 2 == 0;\n * }\n *\n * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));\n * // => [1, 3, 5]\n */\nfunction negate(predicate) {\n if (typeof predicate != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n return function() {\n var args = arguments;\n switch (args.length) {\n case 0: return !predicate.call(this);\n case 1: return !predicate.call(this, args[0]);\n case 2: return !predicate.call(this, args[0], args[1]);\n case 3: return !predicate.call(this, args[0], args[1], args[2]);\n }\n return !predicate.apply(this, args);\n };\n}\n\nexport default negate;\n","/**\n * Check several parameter that there is something in the param\n * @param {*} param input\n * @return {boolean}\n */\nimport { trim, isArray } from 'lodash-es'\n\nexport default a => {\n if (isArray(a)) {\n return true;\n }\n return a !== undefined && a !== null && trim(a) !== '';\n}\n","// validator numbers\n// import { NUMBER_TYPES } from './constants';\nimport { isNaN, isString } from 'lodash-es'\n/**\n * @2015-05-04 found a problem if the value is a number like string\n * it will pass, so add a check if it's string before we pass to next\n * @param {number} value expected value\n * @return {boolean} true if OK\n */\nconst checkIsNumber = function(value) {\n return isString(value) ? false : !isNaN( parseFloat(value) )\n}\n\nexport default checkIsNumber\n","// validate string type\nimport { isString, trim } from 'lodash-es'\n/**\n * @param {string} value expected value\n * @return {boolean} true if OK\n */\nconst checkIsString = function(value) {\n return (trim(value) !== '') ? isString(value) : false;\n}\n\nexport default checkIsString;\n","// check for boolean\nimport { isBoolean } from 'lodash-es'\n/**\n * @param {boolean} value expected\n * @return {boolean} true if OK\n */\nconst checkIsBoolean = function(value) {\n return isBoolean(value);\n};\n\nexport default checkIsBoolean\n","// validate any thing only check if there is something\nimport { isNull, trim, isUndefined } from 'lodash-es'\n/**\n * @param {*} value the value\n * @param {boolean} [checkNull=true] strict check if there is null value\n * @return {boolean} true is OK\n */\nconst checkIsAny = function(value, checkNull = true) {\n if (!isUndefined(value) && value !== '' && trim(value) !== '') {\n if (checkNull === false || (checkNull === true && !isNull(value))) {\n return true;\n }\n }\n return false;\n};\n\nexport default checkIsAny\n","// Good practice rule - No magic number\n\nexport const ARGS_NOT_ARRAY_ERR = `args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)`;\nexport const PARAMS_NOT_ARRAY_ERR = `params is not an array! Did something gone wrong when you generate the contract.json?`;\nexport const EXCEPTION_CASE_ERR = 'Could not understand your arguments and parameter structure!';\nexport const UNUSUAL_CASE_ERR = 'This is an unusual situation where the arguments are more than the params, but not mark as spread';\n\n// re-export\nimport * as JSONQL_CONSTANTS from 'jsonql-constants';\n// @TODO the jsdoc return array. and we should also allow array syntax\nexport const DEFAULT_TYPE = JSONQL_CONSTANTS.DEFAULT_TYPE;\nexport const ARRAY_TYPE_LFT = JSONQL_CONSTANTS.ARRAY_TYPE_LFT;\nexport const ARRAY_TYPE_RGT = JSONQL_CONSTANTS.ARRAY_TYPE_RGT;\n\nexport const TYPE_KEY = JSONQL_CONSTANTS.TYPE_KEY;\nexport const OPTIONAL_KEY = JSONQL_CONSTANTS.OPTIONAL_KEY;\nexport const ENUM_KEY = JSONQL_CONSTANTS.ENUM_KEY;\nexport const ARGS_KEY = JSONQL_CONSTANTS.ARGS_KEY;\nexport const CHECKER_KEY = JSONQL_CONSTANTS.CHECKER_KEY;\nexport const ALIAS_KEY = JSONQL_CONSTANTS.ALIAS_KEY;\n\nexport const ARRAY_TYPE = JSONQL_CONSTANTS.ARRAY_TYPE;\nexport const OBJECT_TYPE = JSONQL_CONSTANTS.OBJECT_TYPE;\nexport const STRING_TYPE = JSONQL_CONSTANTS.STRING_TYPE;\nexport const BOOLEAN_TYPE = JSONQL_CONSTANTS.BOOLEAN_TYPE;\nexport const NUMBER_TYPE = JSONQL_CONSTANTS.NUMBER_TYPE;\nexport const KEY_WORD = JSONQL_CONSTANTS.KEY_WORD;\nexport const OR_SEPERATOR = JSONQL_CONSTANTS.OR_SEPERATOR;\n\n// not actually in use\n// export const NUMBER_TYPES = JSONQL_CONSTANTS.NUMBER_TYPES;\n","// primitive types\nimport checkIsNumber from './number'\nimport checkIsString from './string'\nimport checkIsBoolean from './boolean'\nimport checkIsAny from './any'\nimport { NUMBER_TYPE, STRING_TYPE, BOOLEAN_TYPE } from './constants'\n\n/**\n * this is a wrapper method to call different one based on their type\n * @param {string} type to check\n * @return {function} a function to handle the type\n */\nconst combineFn = function(type) {\n switch (type) {\n case NUMBER_TYPE:\n return checkIsNumber;\n case STRING_TYPE:\n return checkIsString;\n case BOOLEAN_TYPE:\n return checkIsBoolean;\n default:\n return checkIsAny;\n }\n}\n\nexport default combineFn\n","// validate array type\nimport { isArray, trim } from 'lodash-es'\nimport combineFn from './combine'\nimport {\n ARRAY_TYPE_LFT,\n ARRAY_TYPE_RGT,\n OR_SEPERATOR\n} from './constants'\n\n/**\n * @param {array} value expected\n * @param {string} [type=''] pass the type if we encounter array. then we need to check the value as well\n * @return {boolean} true if OK\n */\nexport const checkIsArray = function(value, type='') {\n if (isArray(value)) {\n if (type === '' || trim(type)==='') {\n return true;\n }\n // we test it in reverse\n // @TODO if the type is an array (OR) then what?\n // we need to take into account this could be an array\n const c = value.filter(v => !combineFn(type)(v))\n return !(c.length > 0)\n }\n return false;\n}\n\n/**\n * check if it matches the array. pattern\n * @param {string} type\n * @return {boolean|array} false means NO, always return array\n */\nexport const isArrayLike = function(type) {\n // @TODO could that have something like array<> instead of array.<>? missing the dot?\n // because type script is Array without the dot\n if (type.indexOf(ARRAY_TYPE_LFT) > -1 && type.indexOf(ARRAY_TYPE_RGT) > -1) {\n const _type = type.replace(ARRAY_TYPE_LFT, '').replace(ARRAY_TYPE_RGT, '')\n if (_type.indexOf(OR_SEPERATOR)) {\n return _type.split(OR_SEPERATOR)\n }\n return [_type]\n }\n return false;\n}\n\n/**\n * we might encounter something like array. then we need to take it apart\n * @param {object} p the prepared object for processing\n * @param {string|array} type the type came from \n * @return {boolean} for the filter to operate on\n */\nexport const arrayTypeHandler = function(p, type) {\n const { arg } = p;\n // need a special case to handle the OR type\n // we need to test the args instead of the type(s)\n if (type.length > 1) {\n return !arg.filter(v => (\n !(type.length > type.filter(t => !combineFn(t)(v)).length)\n )).length;\n }\n // type is array so this will be or!\n return type.length > type.filter(t => !checkIsArray(arg, t)).length;\n}\n","// validate object type\nimport { isPlainObject, isUndefined, filter } from 'lodash-es'\nimport combineFn from './combine'\nimport { checkIsArray, isArrayLike, arrayTypeHandler } from './array'\n/**\n * @TODO if provide with the keys then we need to check if the key:value type as well\n * @param {object} value expected\n * @param {array} [keys=null] if it has the keys array to compare as well\n * @return {boolean} true if OK\n */\nexport const checkIsObject = function(value, keys=null) {\n if (isPlainObject(value)) {\n if (!keys) {\n return true;\n }\n if (checkIsArray(keys)) {\n // please note we DON'T care if some is optional\n // plese refer to the contract.json for the keys\n return !keys.filter(key => {\n let _value = value[key.name];\n return !(key.type.length > key.type.filter(type => {\n let tmp;\n if (!isUndefined(_value)) {\n if ((tmp = isArrayLike(type)) !== false) {\n return !arrayTypeHandler({arg: _value}, tmp)\n // return tmp.filter(t => !checkIsArray(_value, t)).length;\n // @TODO there might be an object within an object with keys as well :S\n }\n return !combineFn(type)(_value)\n }\n return true;\n }).length)\n }).length;\n }\n }\n return false;\n}\n\n/**\n * fold this into it's own function to handler different object type\n * @param {object} p the prepared object for process\n * @return {boolean}\n */\nexport const objectTypeHandler = function(p) {\n const { arg, param } = p;\n let _args = [arg];\n if (Array.isArray(param.keys) && param.keys.length) {\n _args.push(param.keys)\n }\n // just simple check\n return checkIsObject.apply(null, _args)\n}\n","// move the index.js code here that make more sense to find where things are\nimport { isUndefined } from 'lodash-es'\nimport {\n checkIsArray,\n isArrayLike,\n arrayTypeHandler,\n objectTypeHandler,\n checkIsObject,\n combineFn,\n notEmpty\n} from './index'\nimport {\n DEFAULT_TYPE,\n ARRAY_TYPE,\n OBJECT_TYPE,\n ARGS_NOT_ARRAY_ERR,\n PARAMS_NOT_ARRAY_ERR,\n EXCEPTION_CASE_ERR,\n UNUSUAL_CASE_ERR\n} from './constants'\nimport { DATA_KEY, ERROR_KEY } from 'jsonql-constants'\nimport { JsonqlError } from 'jsonql-errors'\n\n// import debug from 'debug'\n// const debugFn = debug('jsonql-params-validator:validator')\n// also export this for use in other places\n\n/**\n * We need to handle those optional parameter without a default value\n * @param {object} params from contract.json\n * @return {boolean} for filter operation false is actually OK\n */\nconst optionalHandler = function( params ) {\n const { arg, param } = params;\n if (notEmpty(arg)) {\n // debug('call optional handler', arg, params);\n // loop through the type in param\n return !(param.type.length > param.type.filter(type =>\n validateHandler(type, params)\n ).length)\n }\n return false;\n}\n\n/**\n * actually picking the validator\n * @param {*} type for checking\n * @param {*} value for checking\n * @return {boolean} true on OK\n */\nconst validateHandler = function(type, value) {\n let tmp;\n switch (true) {\n case type === OBJECT_TYPE:\n // debugFn('call OBJECT_TYPE')\n return !objectTypeHandler(value)\n case type === ARRAY_TYPE:\n // debugFn('call ARRAY_TYPE')\n return !checkIsArray(value.arg)\n // @TODO when the type is not present, it always fall through here\n // so we need to find a way to actually pre-check the type first\n // AKA check the contract.json map before running here\n case (tmp = isArrayLike(type)) !== false:\n // debugFn('call ARRAY_LIKE: %O', value)\n return !arrayTypeHandler(value, tmp)\n default:\n return !combineFn(type)(value.arg)\n }\n}\n\n/**\n * it get too longer to fit in one line so break it out from the fn below\n * @param {*} arg value\n * @param {object} param config\n * @return {*} value or apply default value\n */\nconst getOptionalValue = function(arg, param) {\n if (!isUndefined(arg)) {\n return arg;\n }\n return (param.optional === true && !isUndefined(param.defaultvalue) ? param.defaultvalue : null)\n}\n\n/**\n * padding the arguments with defaultValue if the arguments did not provide the value\n * this will be the name export\n * @param {array} args normalized arguments\n * @param {array} params from contract.json\n * @return {array} merge the two together\n */\nexport const normalizeArgs = function(args, params) {\n // first we should check if this call require a validation at all\n // there will be situation where the function doesn't need args and params\n if (!checkIsArray(params)) {\n // debugFn('params value', params)\n throw new JsonqlError(PARAMS_NOT_ARRAY_ERR)\n }\n if (params.length === 0) {\n return [];\n }\n if (!checkIsArray(args)) {\n throw new JsonqlError(ARGS_NOT_ARRAY_ERR)\n }\n // debugFn(args, params);\n // fall through switch\n switch(true) {\n case args.length == params.length: // standard\n return args.map((arg, i) => (\n {\n arg,\n index: i,\n param: params[i]\n }\n ));\n case params[0].variable === true: // using spread syntax\n const type = params[0].type;\n return args.map((arg, i) => (\n {\n arg,\n index: i, // keep the index for reference\n param: params[i] || { type, name: '_' }\n }\n ));\n // with optional defaultValue parameters\n case args.length < params.length:\n return params.map((param, i) => (\n {\n param,\n index: i,\n arg: getOptionalValue(args[i], param),\n optional: param.optional || false\n }\n ));\n // this one pass more than it should have anything after the args.length will be cast as any type\n case args.length > params.length && params.length === 1:\n // this happens when we have those array. type\n let tmp, _type = [ DEFAULT_TYPE ];\n // we only looking at the first one, this might be a @BUG!\n if ((tmp = isArrayLike(params[0].type[0])) !== false) {\n _type = tmp;\n }\n // if not then we fall back to the following\n return args.map((arg, i) => (\n {\n arg,\n index: i,\n param: params[i] || { type: _type, name: '_' }\n }\n ));\n // @TODO find out if there is more cases not cover\n default: // this should never happen\n // debugFn('args', args)\n // debugFn('params', params)\n // this is unknown therefore we just throw it!\n throw new JsonqlError(EXCEPTION_CASE_ERR, { args, params })\n }\n}\n\n// what we want is after the validaton we also get the normalized result\n// which is with the optional property if the argument didn't provide it\n/**\n * process the array of params back to their arguments\n * @param {array} result the params result\n * @return {array} arguments\n */\nconst processReturn = result => result.map(r => r.arg)\n\n/**\n * validator main interface\n * @param {array} args the arguments pass to the method call\n * @param {array} params from the contract for that method\n * @param {boolean} [withResul=false] if true then this will return the normalize result as well\n * @return {array} empty array on success, or failed parameter and reasons\n */\nexport const validateSync = function(args, params, withResult = false) {\n let cleanArgs = normalizeArgs(args, params)\n let checkResult = cleanArgs.filter(p => {\n if (p.param.optional === true) {\n return optionalHandler(p)\n }\n // because array of types means OR so if one pass means pass\n return !(p.param.type.length > p.param.type.filter(\n type => validateHandler(type, p)\n ).length)\n })\n // using the same convention we been using all this time\n return !withResult ? checkResult : {\n [ERROR_KEY]: checkResult,\n [DATA_KEY]: processReturn(cleanArgs)\n }\n}\n\n/**\n * A wrapper method that return promise\n * @param {array} args arguments\n * @param {array} params from contract.json\n * @param {boolean} [withResul=false] if true then this will return the normalize result as well\n * @return {object} promise.then or catch\n */\nexport const validateAsync = function(args, params, withResult = false) {\n return new Promise((resolver, rejecter) => {\n const result = validateSync(args, params, withResult)\n if (withResult) {\n return result[ERROR_KEY].length ? rejecter(result[ERROR_KEY])\n : resolver(result[DATA_KEY])\n }\n // the different is just in the then or catch phrase\n return result.length ? rejecter(result) : resolver([])\n })\n}\n","/**\n * @param {array} arr Array for check\n * @param {*} value target\n * @return {boolean} true on successs\n */\nconst isInArray = function(arr, value) {\n return !!arr.filter(a => a === value).length;\n}\n\nexport default isInArray\n","// breaking the whole thing up to see what cause the multiple calls issue\n\nimport { isFunction, merge, mapValues } from 'lodash-es'\n\nimport {\n TYPE_KEY,\n OPTIONAL_KEY,\n ENUM_KEY,\n ARGS_KEY,\n CHECKER_KEY,\n KEY_WORD\n} from '../constants'\nimport {\n JsonqlEnumError,\n JsonqlTypeError,\n JsonqlCheckerError\n} from 'jsonql-errors'\nimport { checkIsArray } from '../array'\n\n// import debug from 'debug';\n// const debugFn = debug('jsonql-params-validator:options:validation')\n\n/**\n * just make sure it returns an array to use\n * @param {*} arg input\n * @return {array} output\n */\nconst toArray = arg => checkIsArray(arg) ? arg : [arg]\n\n/**\n * DIY in array\n * @param {array} arr to check against\n * @param {*} value to check\n * @return {boolean} true on OK\n */\nconst inArray = (arr, value) => (\n !!arr.filter(v => v === value).length\n)\n\n/**\n * break out to make the code easier to read\n * @param {object} value to process\n * @param {function} cb the validateSync\n * @return {array} empty on success\n */\nfunction validateHandler(value, cb) {\n // cb is the validateSync methods\n let args = [\n [ value[ARGS_KEY] ],\n [{\n [TYPE_KEY]: toArray(value[TYPE_KEY]),\n [OPTIONAL_KEY]: value[OPTIONAL_KEY]\n }]\n ]\n // debugFn('validateHandler', args)\n return Reflect.apply(cb, null, args)\n}\n\n/**\n * Check against the enum value if it's provided\n * @param {*} value to check\n * @param {*} enumv to check against if it's not false\n * @return {boolean} true on OK\n */\nconst enumHandler = (value, enumv) => {\n if (checkIsArray(enumv)) {\n return inArray(enumv, value)\n }\n return true;\n}\n\n/**\n * Allow passing a function to check the value\n * There might be a problem here if the function is incorrect\n * and that will makes it hard to debug what is going on inside\n * @TODO there could be a few feature add to this one under different circumstance\n * @param {*} value to check\n * @param {function} checker for checking\n */\nconst checkerHandler = (value, checker) => {\n try {\n return isFunction(checker) ? checker.apply(null, [value]) : false;\n } catch (e) {\n return false;\n }\n}\n\n/**\n * Taken out from the runValidaton this only validate the required values\n * @param {array} args from the config2argsAction\n * @param {function} cb validateSync\n * @return {array} of configuration values\n */\nfunction runValidationAction(cb) {\n return (value, key) => {\n // debugFn('runValidationAction', key, value)\n if (value[KEY_WORD]) {\n return value[ARGS_KEY]\n }\n const check = validateHandler(value, cb)\n if (check.length) {\n // debugFn('runValidationAction', key, value)\n throw new JsonqlTypeError(key, check)\n }\n if (value[ENUM_KEY] !== false && !enumHandler(value[ARGS_KEY], value[ENUM_KEY])) {\n throw new JsonqlEnumError(key)\n }\n if (value[CHECKER_KEY] !== false && !checkerHandler(value[ARGS_KEY], value[CHECKER_KEY])) {\n throw new JsonqlCheckerError(key)\n }\n return value[ARGS_KEY]\n }\n}\n\n/**\n * @param {object} args from the config2argsAction\n * @param {function} cb validateSync\n * @return {object} of configuration values\n */\nexport default function runValidation(args, cb) {\n const [ argsForValidate, pristineValues ] = args;\n // turn the thing into an array and see what happen here\n // debugFn('_args', argsForValidate)\n const result = mapValues(argsForValidate, runValidationAction(cb))\n return merge(result, pristineValues)\n}\n","// this is port back from the client to share across all projects\nimport { merge } from 'lodash-es'\nimport { prepareArgsForValidation } from './prepare-args-for-validation'\nimport runValidation from './run-validation'\n\n// import debug from 'debug'\n// const debugFn = debug('jsonql-params-validator:check-options-async')\n\n/**\n * Quick transform\n * @param {object} config that one\n * @param {object} appProps mutation configuration options\n * @return {object} put that arg into the args\n */\nconst configToArgs = (config, appProps) => {\n return Promise.resolve(\n prepareArgsForValidation(config, appProps)\n )\n}\n\n/**\n * @param {object} config user provide configuration option\n * @param {object} appProps mutation configuration options\n * @param {object} constProps the immutable configuration options\n * @param {function} cb the validateSync method\n * @return {object} Promise resolve merge config object\n */\nexport default function(config = {}, appProps, constProps, cb) {\n return configToArgs(config, appProps)\n .then(args1 => {\n // debugFn('args', args1)\n return runValidation(args1, cb)\n })\n // next if every thing good then pass to final merging\n .then(args2 => merge({}, args2, constProps))\n}\n","// create function to construct the config entry so we don't need to keep building object\nimport {\n ARGS_KEY,\n TYPE_KEY,\n CHECKER_KEY,\n ENUM_KEY,\n OPTIONAL_KEY,\n ALIAS_KEY\n} from 'jsonql-constants';\nimport { checkIsArray } from '../array';\nimport checkIsBoolean from '../boolean';\nimport { isFunction, isString } from 'lodash-es';\n// import debug from 'debug';\n// const debugFn = debug('jsonql-params-validator:construct-config');\n/**\n * @param {*} args value\n * @param {string} type for value\n * @param {boolean} [optional=false]\n * @param {boolean|array} [enumv=false]\n * @param {boolean|function} [checker=false]\n * @return {object} config entry\n */\nexport default function(args, type, optional=false, enumv=false, checker=false, alias=false) {\n let base = {\n [ARGS_KEY]: args,\n [TYPE_KEY]: type\n };\n if (optional === true) {\n base[OPTIONAL_KEY] = true;\n }\n if (checkIsArray(enumv)) {\n base[ENUM_KEY] = enumv;\n }\n if (isFunction(checker)) {\n base[CHECKER_KEY] = checker;\n }\n if (isString(alias)) {\n base[ALIAS_KEY] = alias;\n }\n return base;\n};\n","// export also create wrapper methods\nimport checkOptionsAsync from './check-options-async'\nimport checkOptionsSync from './check-options-sync'\nimport constructConfigFn from './construct-config'\nimport {\n ENUM_KEY,\n CHECKER_KEY,\n ALIAS_KEY,\n OPTIONAL_KEY\n} from 'jsonql-constants'\n\n// import debug from 'debug';\n// const debugFn = debug('jsonql-params-validator:options:index');\n\n/**\n * This has a different interface\n * @param {*} value to supply\n * @param {string|array} type for checking\n * @param {object} params to map against the config check\n * @param {array} params.enumv NOT enum\n * @param {boolean} params.optional false then nothing\n * @param {function} params.checker need more work on this one later\n * @param {string} params.alias mostly for cmd\n */\nconst createConfig = (value, type, params = {}) => {\n // Note the enumv not ENUM\n // const { enumv, optional, checker, alias } = params;\n // let args = [value, type, optional, enumv, checker, alias];\n const {\n [OPTIONAL_KEY]: o,\n [ENUM_KEY]: e,\n [CHECKER_KEY]: c,\n [ALIAS_KEY]: a\n } = params;\n return constructConfigFn.apply(null, [value, type, o, e, c, a])\n}\n\n// for testing purpose\nconst JSONQL_PARAMS_VALIDATOR_INFO = '__PLACEHOLDER__';\n\n/**\n * We recreate the method here to avoid the circlar import\n * @param {object} config user supply configuration\n * @param {object} appProps mutation options\n * @param {object} [constantProps={}] optional: immutation options\n * @return {object} all checked configuration\n */\nconst checkConfigAsync = function(validateSync) {\n return function(config, appProps, constantProps= {}) {\n return checkOptionsAsync(config, appProps, constantProps, validateSync)\n }\n}\n\n// copy of above but it's sync\nconst checkConfig = function(validateSync) {\n return function(config, appProps, constantProps = {}) {\n return checkOptionsSync(config, appProps, constantProps, validateSync)\n }\n}\n\n// re-export\nexport {\n createConfig,\n constructConfigFn,\n checkConfigAsync,\n checkConfig,\n JSONQL_PARAMS_VALIDATOR_INFO\n}\n","// since this need to use everywhere might as well include in the validator\nimport { QUERY_NAME, MUTATION_NAME, SOCKET_NAME } from 'jsonql-constants'\nimport checkKeyInObject from './check-key-in-object'\nimport { checkIsObject } from './object'\n\nexport default function(contract) {\n return checkIsObject(contract)\n && (\n checkKeyInObject(contract, QUERY_NAME)\n || checkKeyInObject(contract, MUTATION_NAME)\n || checkKeyInObject(contract, SOCKET_NAME)\n )\n}\n","// craete several helper function to construct / extract the payload\n// and make sure they are all the same\nimport {\n PAYLOAD_PARAM_NAME,\n CONDITION_PARAM_NAME,\n RESOLVER_PARAM_NAME,\n QUERY_ARG_NAME\n} from 'jsonql-constants'\nimport { JsonqlValidationError } from 'jsonql-errors'\n\nimport isString from './string'\nimport { checkIsArray } from './array'\nimport { checkIsObject } from './object'\n\n// make sure it's an object\nconst formatPayload = payload => isString(payload) ? JSON.parse(payload) : payload;\n\n/**\n * Get name from the payload (ported back from jsonql-koa)\n * @param {*} payload to extract from\n * @return {string} name\n */\nexport function getNameFromPayload(payload) {\n return Object.keys(payload)[0]\n}\n\n/**\n * @param {string} resolverName name of function\n * @param {array} [args=[]] from the ...args\n * @param {boolean} [jsonp = false] add v1.3.0 to koa\n * @return {object} formatted argument\n */\nexport function createQuery(resolverName, args = [], jsonp = false) {\n if (isString(resolverName) && checkIsArray(args)) {\n let payload = { [QUERY_ARG_NAME]: args }\n if (jsonp === true) {\n return payload;\n }\n return { [resolverName]: payload }\n }\n throw new JsonqlValidationError(`[createQuery] expect resolverName to be string and args to be array!`, { resolverName, args })\n}\n\n// string version of the above\nexport function createQueryStr(resolverName, args = [], jsonp = false) {\n return JSON.stringify(createQuery(resolverName, args, jsonp))\n}\n\n/**\n * @param {string} resolverName name of function\n * @param {*} payload to send\n * @param {object} [condition={}] for what\n * @param {boolean} [jsonp = false] add v1.3.0 to koa\n * @return {object} formatted argument\n */\nexport function createMutation(resolverName, payload, condition = {}, jsonp = false) {\n const _payload = {\n [PAYLOAD_PARAM_NAME]: payload,\n [CONDITION_PARAM_NAME]: condition\n }\n if (jsonp === true) {\n return _payload;\n }\n if (isString(resolverName)) {\n return { [resolverName]: _payload }\n }\n throw new JsonqlValidationError(`[createMutation] expect resolverName to be string!`, { resolverName, payload, condition })\n}\n\n// string version of above\nexport function createMutationStr(resolverName, payload, condition = {}, jsonp = false) {\n return JSON.stringify(createMutation(resolverName, payload, condition, jsonp))\n}\n\n/**\n * Further break down from method below for use else where\n * @param {string} resolverName name of fn\n * @param {object} payload payload\n * @return {object|boolean} false on failed\n */\nexport function getQueryFromArgs(resolverName, payload) {\n if (resolverName && checkIsObject(payload)) {\n const args = payload[resolverName];\n if (args[QUERY_ARG_NAME]) {\n return {\n [RESOLVER_PARAM_NAME]: resolverName,\n [QUERY_ARG_NAME]: args[QUERY_ARG_NAME]\n }\n }\n }\n return false;\n}\n\n/**\n * extra the payload back\n * @param {*} payload from http call\n * @return {object} resolverName and args\n */\nexport function getQueryFromPayload(payload) {\n const p = formatPayload(payload);\n const resolverName = getNameFromPayload(p)\n const result = getQueryFromArgs(resolverName, p)\n if (result !== false) {\n return result;\n }\n throw new JsonqlValidationError('[getQueryArgs] Payload is malformed!', payload)\n}\n\n/**\n * Further break down from method below for use else where\n * @param {string} resolverName name of fn\n * @param {object} payload payload\n * @return {object|boolean} false on failed\n */\nexport function getMutationFromArgs(resolverName, payload) {\n if (resolverName && checkIsObject(payload)) {\n const args = payload[resolverName]\n if (args) {\n return {\n [RESOLVER_PARAM_NAME]: resolverName,\n [PAYLOAD_PARAM_NAME]: args[PAYLOAD_PARAM_NAME],\n [CONDITION_PARAM_NAME]: args[CONDITION_PARAM_NAME]\n }\n }\n }\n return false;\n}\n\n/**\n * @param {object} payload\n * @return {object} resolverName, payload, conditon\n */\nexport function getMutationFromPayload(payload) {\n const p = formatPayload(payload);\n const resolverName = getNameFromPayload(p)\n const result = getMutationFromArgs(resolverName, p)\n if (result !== false) {\n return result;\n }\n throw new JsonqlValidationError('[getMutationArgs] Payload is malformed!', payload)\n}\n","// export\nimport {\n checkIsObject,\n notEmpty,\n checkIsAny,\n checkIsString,\n checkIsBoolean,\n checkIsNumber,\n checkIsArray\n} from './src'\n// PIA syntax\nexport const isObject = checkIsObject;\nexport const isAny = checkIsAny;\nexport const isString = checkIsString;\nexport const isBoolean = checkIsBoolean;\nexport const isNumber = checkIsNumber;\nexport const isArray = checkIsArray;\nexport const isNotEmpty = notEmpty;\n\nimport * as validator from './src/validator'\n\nexport const normalizeArgs = validator.normalizeArgs;\nexport const validateSync = validator.validateSync;\nexport const validateAsync = validator.validateAsync;\n\n// configuration checking\n\nimport * as jsonqlOptions from './src/options'\n\nexport const JSONQL_PARAMS_VALIDATOR_INFO = jsonqlOptions.JSONQL_PARAMS_VALIDATOR_INFO;\n\nexport const createConfig = jsonqlOptions.createConfig;\nexport const constructConfig = jsonqlOptions.constructConfigFn;\n\nexport const checkConfigAsync = jsonqlOptions.checkConfigAsync(validator.validateSync)\nexport const checkConfig = jsonqlOptions.checkConfig(validator.validateSync)\n\nimport isInArray from './src/is-in-array'\n\nexport const inArray = isInArray;\n\nimport checkKeyInObject from './src/check-key-in-object'\n\nexport const isKeyInObject = checkKeyInObject;\n\nimport checkIsContract from './src/check-is-contract'\n\nexport const isContract = checkIsContract;\n\n// add in v1.3.0\n\nimport * as paramsApi from './src/params-api'\n\nexport const createQuery = paramsApi.createQuery;\nexport const createQueryStr = paramsApi.createQueryStr;\nexport const createMutation = paramsApi.createMutation;\nexport const createMutationStr = paramsApi.createMutationStr;\nexport const getQueryFromArgs = paramsApi.getQueryFromArgs;\nexport const getQueryFromPayload = paramsApi.getQueryFromPayload;\nexport const getMutationFromArgs = paramsApi.getMutationFromArgs;\nexport const getMutationFromPayload = paramsApi.getMutationFromPayload;\nexport const getNameFromPayload = paramsApi.getNameFromPayload;\n","// This is ported back from ws-server and it will get use in the server / client side\nimport { isKeyInObject } from 'jsonql-params-validator'\n\nfunction extractSocketPart(contract) {\n if (isKeyInObject(contract, 'socket')) {\n return contract.socket;\n }\n return contract;\n}\n\n/**\n * @BUG we should check the socket part instead of expect the downstream to read the menu!\n * We only need this when the enableAuth is true otherwise there is only one namespace\n * @param {object} contract the socket part of the contract file\n * @return {object} 1. remap the contract using the namespace --> resolvers\n * 2. the size of the object (1 all private, 2 mixed public with private)\n * 3. which namespace is public\n */\nexport default function groupByNamespace(contract) {\n let socket = extractSocketPart(contract)\n\n let nspSet = {};\n let size = 0;\n let publicNamespace;\n for (let resolverName in socket) {\n let params = socket[resolverName];\n let { namespace } = params;\n if (namespace) {\n if (!nspSet[namespace]) {\n ++size;\n nspSet[namespace] = {};\n }\n nspSet[namespace][resolverName] = params;\n if (!publicNamespace) {\n if (params.public) {\n publicNamespace = namespace;\n }\n }\n }\n }\n return { size, nspSet, publicNamespace }\n}\n","// This is ported back from ws-client\n// the idea if from https://decembersoft.com/posts/promises-in-serial-with-array-reduce/\n/**\n * previously we already make sure the order of the namespaces\n * and attach the auth client to it\n * @param {array} promises array of unresolved promises\n * @return {object} promise resolved with the array of promises resolved results\n */\nexport default function chainPromises(promises) {\n return promises.reduce((promiseChain, currentTask) => (\n promiseChain.then(chainResults => (\n currentTask.then(currentResult => (\n [...chainResults, currentResult]\n ))\n ))\n ), Promise.resolve([]))\n}\n","/**\n * The code was extracted from:\n * https://github.com/davidchambers/Base64.js\n */\n\nvar chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n\nfunction InvalidCharacterError(message) {\n this.message = message;\n}\n\nInvalidCharacterError.prototype = new Error();\nInvalidCharacterError.prototype.name = 'InvalidCharacterError';\n\nfunction polyfill (input) {\n var str = String(input).replace(/=+$/, '');\n if (str.length % 4 == 1) {\n throw new InvalidCharacterError(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n for (\n // initialize result and counters\n var bc = 0, bs, buffer, idx = 0, output = '';\n // get next character\n buffer = str.charAt(idx++);\n // character found in table? initialize bit storage and add its ascii value;\n ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,\n // and if not first of each 4 characters,\n // convert the first 8 bits to one ascii character\n bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0\n ) {\n // try to find character in table (0-63, not found => -1)\n buffer = chars.indexOf(buffer);\n }\n return output;\n}\n\n\nmodule.exports = typeof window !== 'undefined' && window.atob && window.atob.bind(window) || polyfill;\n","// ws client using native WebSocket\nimport { JsonqlValidationError } from 'jsonql-errors';\n\nexport default function getWS() {\n switch(true) {\n case (typeof WebSocket !== 'undefined'):\n return WebSocket;\n case (typeof MozWebSocket !== 'undefined'):\n return MozWebSocket;\n // case (typeof global !== 'undefined'):\n // return global.WebSocket || global.MozWebSocket;\n case (typeof window !== 'undefined'):\n return window.WebSocket || window.MozWebSocket;\n // case (typeof self !== 'undefined'):\n // return self.WebSocket || self.MozWebSocket;\n default:\n throw new JsonqlValidationError('WebSocket is NOT SUPPORTED!')\n }\n}\n","// constants\n\nimport {\n EMIT_REPLY_TYPE,\n JS_WS_SOCKET_IO_NAME,\n JS_WS_NAME,\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME\n} from 'jsonql-constants'\n\nconst SOCKET_IO = JS_WS_SOCKET_IO_NAME;\nconst WS = JS_WS_NAME;\n\nconst AVAILABLE_SERVERS = [SOCKET_IO, WS]\n\nconst SOCKET_NOT_DEFINE_ERR = 'socket is not define in the contract file!';\n\nconst SERVER_NOT_SUPPORT_ERR = 'is not supported server name!';\n\nconst MISSING_PROP_ERR = 'Missing property in contract!';\n\nconst UNKNOWN_CLIENT_ERR = 'Unknown client type!';\n\nconst EMIT_EVT = EMIT_REPLY_TYPE;\n\nconst NAMESPACE_KEY = 'namespaceMap';\n\nconst UNKNOWN_RESULT = 'UKNNOWN RESULT!';\n\nconst NOT_ALLOW_OP = 'This operation is not allow!';\n\nconst MY_NAMESPACE = 'myNamespace'\n\nexport {\n SOCKET_IO,\n WS,\n AVAILABLE_SERVERS,\n SOCKET_NOT_DEFINE_ERR,\n SERVER_NOT_SUPPORT_ERR,\n MISSING_PROP_ERR,\n UNKNOWN_CLIENT_ERR,\n EMIT_EVT,\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME,\n NAMESPACE_KEY,\n UNKNOWN_RESULT,\n NOT_ALLOW_OP,\n MY_NAMESPACE\n}\n","// generate the web socket connect client for browser\nimport {\n socketIoRoundtripLogin,\n socketIoClientAsync,\n socketIoHandshakeLogin,\n wsAuthClient,\n wsClient\n} from 'jsonql-jwt'\n\nimport { isString } from 'jsonql-params-validator'\nimport { JsonqlError } from 'jsonql-errors'\nimport { SOCKET_IO, WS } from './constants'\n// import { IO_ROUNDTRIP_LOGIN, IO_HANDSHAKE_LOGIN } from 'jsonql-constants'\nimport getDebug from './get-debug'\nconst debug = getDebug('client-generator')\n\n/**\n * create the web socket client\n * @param {object} payload passing\n * @return {object} just mutate it then pass it on\n */\nexport default function clientGenerator({opts, nspMap, ee}) {\n switch (opts.serverType) {\n case SOCKET_IO:\n opts.nspClient = (...args) => (\n Reflect.apply(socketIoClientAsync, null, [io, ...args])\n )\n if (isString(opts.useJwt)) {\n opts.nspAuthClient = (...args) => (\n Reflect.apply(socketIoRoundtripLogin, null, [io, ...args])\n )\n } else {\n opts.nspAuthClient = (...args) => (\n Reflect.apply(socketIoHandshakeLogin, null, [io, ...args])\n )\n }\n break;\n case WS:\n opts.nspClient = wsClient;\n opts.nspAuthClient = wsAuthClient;\n break;\n default:\n throw new JsonqlError(`Unknown serverType: ${opts.serverType}`)\n }\n return {opts, nspMap, ee}\n}\n","// since both the ws and io version are\n// pre-defined in the client-generator\n// and this one will have the same parameters\n// and the callback is identical\nimport getDebug from './get-debug'\nconst debugFn = getDebug('create-nsp-client')\n/**\n * wrapper method to create a nsp without login\n * @param {string|boolean} namespace namespace url could be false\n * @param {object} opts configuration\n * @return {object} ws client instance\n */\nconst nspClient = (namespace, opts) => {\n const { wssPath, wsOptions, hostname } = opts;\n const url = namespace ? [hostname, namespace].join('/') : wssPath;\n return opts.nspClient(url, wsOptions)\n}\n\n/**\n * wrapper method to create a nsp with token auth\n * @param {string} namespace namespace url\n * @param {object} opts configuration\n * @return {object} ws client instance\n */\nconst nspAuthClient = (namespace, opts) => {\n const { wssPath, token, wsOptions, hostname } = opts;\n const url = namespace ? [hostname, namespace].join('/') : wssPath;\n return opts.nspAuthClient(url, token, wsOptions)\n}\n\nexport {\n nspClient,\n nspAuthClient\n}\n","/**\n * generate a 32bit hash based on the function.toString()\n * _from http://stackoverflow.com/questions/7616461/generate-a-hash-_from-string-in-javascript-jquery\n * @param {string} s the converted to string function\n * @return {string} the hashed function string\n */\nexport default function hashCode(s) {\n\treturn s.split(\"\").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0)\n}\n","// making all the functionality on it's own\n// import { WatchClass } from './watch'\n\nexport default class SuspendClass {\n\n constructor() {\n // suspend, release and queue\n this.__suspend__ = null;\n this.queueStore = new Set()\n /*\n this.watch('suspend', function(value, prop, oldValue) {\n this.logger(`${prop} set from ${oldValue} to ${value}`)\n // it means it set the suspend = true then release it\n if (oldValue === true && value === false) {\n // we want this happen after the return happens\n setTimeout(() => {\n this.release()\n }, 1)\n }\n return value; // we need to return the value to store it\n })\n */\n }\n\n /**\n * setter to set the suspend and check if it's boolean value\n * @param {boolean} value to trigger\n */\n set $suspend(value) {\n if (typeof value === 'boolean') {\n const lastValue = this.__suspend__;\n this.__suspend__ = value;\n this.logger('($suspend)', `Change from ${lastValue} --> ${value}`)\n if (lastValue === true && value === false) {\n setTimeout(() => {\n this.release()\n }, 1)\n }\n } else {\n throw new Error(`$suspend only accept Boolean value!`)\n }\n }\n\n /**\n * queuing call up when it's in suspend mode\n * @param {any} value\n * @return {Boolean} true when added or false when it's not\n */\n $queue(...args) {\n if (this.__suspend__ === true) {\n this.logger('($queue)', 'added to $queue', args)\n // there shouldn't be any duplicate ...\n this.queueStore.add(args)\n }\n return this.__suspend__;\n }\n\n /**\n * a getter to get all the store queue\n * @return {array} Set turn into Array before return\n */\n get $queues() {\n let size = this.queueStore.size;\n this.logger('($queues)', `size: ${size}`)\n if (size > 0) {\n return Array.from(this.queueStore)\n }\n return []\n }\n\n /**\n * Release the queue\n * @return {int} size if any\n */\n release() {\n let size = this.queueStore.size\n this.logger('(release)', `Release was called ${size}`)\n if (size > 0) {\n const queue = Array.from(this.queueStore)\n this.queueStore.clear()\n this.logger('queue', queue)\n queue.forEach(args => {\n this.logger(args)\n Reflect.apply(this.$trigger, this, args)\n })\n this.logger(`Release size ${this.queueStore.size}`)\n }\n }\n}\n","// break up the main file because its getting way too long\nimport {\n NB_EVENT_SERVICE_PRIVATE_STORE,\n NB_EVENT_SERVICE_PRIVATE_LAZY\n} from './store'\nimport genHaskKey from './hash-code'\nimport SuspendClass from './suspend'\n\nexport default class NbEventServiceBase extends SuspendClass {\n\n constructor(config = {}) {\n super()\n if (config.logger && typeof config.logger === 'function') {\n this.logger = config.logger;\n }\n this.keep = config.keep;\n // for the $done setter\n this.result = config.keep ? [] : null;\n // we need to init the store first otherwise it could be a lot of checking later\n this.normalStore = new Map()\n this.lazyStore = new Map()\n }\n\n /**\n * validate the event name(s)\n * @param {string[]} evt event name\n * @return {boolean} true when OK\n */\n validateEvt(...evt) {\n evt.forEach(e => {\n if (typeof e !== 'string') {\n this.logger('(validateEvt)', e)\n throw new Error(`event name must be string type!`)\n }\n })\n return true;\n }\n\n /**\n * Simple quick check on the two main parameters\n * @param {string} evt event name\n * @param {function} callback function to call\n * @return {boolean} true when OK\n */\n validate(evt, callback) {\n if (this.validateEvt(evt)) {\n if (typeof callback === 'function') {\n return true;\n }\n }\n throw new Error(`callback required to be function type!`)\n }\n\n /**\n * Check if this type is correct or not added in V1.5.0\n * @param {string} type for checking\n * @return {boolean} true on OK\n */\n validateType(type) {\n const types = ['on', 'only', 'once', 'onlyOnce']\n return !!types.filter(t => type === t).length;\n }\n\n /**\n * Run the callback\n * @param {function} callback function to execute\n * @param {array} payload for callback\n * @param {object} ctx context or null\n * @return {void} the result store in $done\n */\n run(callback, payload, ctx) {\n this.logger('(run)', callback, payload, ctx)\n this.$done = Reflect.apply(callback, ctx, this.toArray(payload))\n }\n\n /**\n * Take the content out and remove it from store id by the name\n * @param {string} evt event name\n * @param {string} [storeName = lazyStore] name of store\n * @return {object|boolean} content or false on not found\n */\n takeFromStore(evt, storeName = 'lazyStore') {\n let store = this[storeName]; // it could be empty at this point\n if (store) {\n this.logger('(takeFromStore)', storeName, store)\n if (store.has(evt)) {\n let content = store.get(evt)\n this.logger('(takeFromStore)', `has ${evt}`, content)\n store.delete(evt)\n return content;\n }\n return false;\n }\n throw new Error(`${storeName} is not supported!`)\n }\n\n /**\n * The add to store step is similar so make it generic for resuse\n * @param {object} store which store to use\n * @param {string} evt event name\n * @param {spread} args because the lazy store and normal store store different things\n * @return {array} store and the size of the store\n */\n addToStore(store, evt, ...args) {\n let fnSet;\n if (store.has(evt)) {\n this.logger('(addToStore)', `${evt} existed`)\n fnSet = store.get(evt)\n } else {\n this.logger('(addToStore)', `create new Set for ${evt}`)\n // this is new\n fnSet = new Set()\n }\n // lazy only store 2 items - this is not the case in V1.6.0 anymore\n // we need to check the first parameter is string or not\n if (args.length > 2) {\n if (Array.isArray(args[0])) { // lazy store\n // check if this type of this event already register in the lazy store\n let [,,t] = args;\n if (!this.checkTypeInLazyStore(evt, t)) {\n fnSet.add(args)\n }\n } else {\n if (!this.checkContentExist(args, fnSet)) {\n this.logger('(addToStore)', `insert new`, args)\n fnSet.add(args)\n }\n }\n } else { // add straight to lazy store\n fnSet.add(args)\n }\n store.set(evt, fnSet)\n return [store, fnSet.size]\n }\n\n /**\n * @param {array} args for compare\n * @param {object} fnSet A Set to search from\n * @return {boolean} true on exist\n */\n checkContentExist(args, fnSet) {\n let list = Array.from(fnSet)\n return !!list.filter(l => {\n let [hash,] = l;\n if (hash === args[0]) {\n return true;\n }\n return false;\n }).length;\n }\n\n /**\n * get the existing type to make sure no mix type add to the same store\n * @param {string} evtName event name\n * @param {string} type the type to check\n * @return {boolean} true you can add, false then you can't add this type\n */\n checkTypeInStore(evtName, type) {\n this.validateEvt(evtName, type)\n let all = this.$get(evtName, true)\n if (all === false) {\n // pristine it means you can add\n return true;\n }\n // it should only have ONE type in ONE event store\n return !all.filter(list => {\n let [ ,,,t ] = list;\n return type !== t;\n }).length;\n }\n\n /**\n * This is checking just the lazy store because the structure is different\n * therefore we need to use a new method to check it\n */\n checkTypeInLazyStore(evtName, type) {\n this.validateEvt(evtName, type)\n let store = this.lazyStore.get(evtName)\n this.logger('(checkTypeInLazyStore)', store)\n if (store) {\n return !!Array\n .from(store)\n .filter(l => {\n let [,,t] = l;\n return t !== type;\n }).length\n }\n return false;\n }\n\n /**\n * wrapper to re-use the addToStore,\n * V1.3.0 add extra check to see if this type can add to this evt\n * @param {string} evt event name\n * @param {string} type on or once\n * @param {function} callback function\n * @param {object} context the context the function execute in or null\n * @return {number} size of the store\n */\n addToNormalStore(evt, type, callback, context = null) {\n this.logger('(addToNormalStore)', evt, type, 'try to add to normal store')\n // @TODO we need to check the existing store for the type first!\n if (this.checkTypeInStore(evt, type)) {\n this.logger('(addToNormalStore)', `${type} can add to ${evt} normal store`)\n let key = this.hashFnToKey(callback)\n let args = [this.normalStore, evt, key, callback, context, type]\n let [_store, size] = Reflect.apply(this.addToStore, this, args)\n this.normalStore = _store;\n return size;\n }\n return false;\n }\n\n /**\n * Add to lazy store this get calls when the callback is not register yet\n * so we only get a payload object or even nothing\n * @param {string} evt event name\n * @param {array} payload of arguments or empty if there is none\n * @param {object} [context=null] the context the callback execute in\n * @param {string} [type=false] register a type so no other type can add to this evt\n * @return {number} size of the store\n */\n addToLazyStore(evt, payload = [], context = null, type = false) {\n // this is add in V1.6.0\n // when there is type then we will need to check if this already added in lazy store\n // and no other type can add to this lazy store\n let args = [this.lazyStore, evt, this.toArray(payload), context]\n if (type) {\n args.push(type)\n }\n let [_store, size] = Reflect.apply(this.addToStore, this, args)\n this.lazyStore = _store;\n return size;\n }\n\n /**\n * make sure we store the argument correctly\n * @param {*} arg could be array\n * @return {array} make sured\n */\n toArray(arg) {\n return Array.isArray(arg) ? arg : [arg];\n }\n\n /**\n * setter to store the Set in private\n * @param {object} obj a Set\n */\n set normalStore(obj) {\n NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj)\n }\n\n /**\n * @return {object} Set object\n */\n get normalStore() {\n return NB_EVENT_SERVICE_PRIVATE_STORE.get(this)\n }\n\n /**\n * setter to store the Set in lazy store\n * @param {object} obj a Set\n */\n set lazyStore(obj) {\n NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj)\n }\n\n /**\n * @return {object} the lazy store Set\n */\n get lazyStore() {\n return NB_EVENT_SERVICE_PRIVATE_LAZY.get(this)\n }\n\n /**\n * generate a hashKey to identify the function call\n * The build-in store some how could store the same values!\n * @param {function} fn the converted to string function\n * @return {string} hashKey\n */\n hashFnToKey(fn) {\n return genHaskKey(fn.toString()) + '';\n }\n}\n","// The top level\nimport NbStoreService from './store-service'\n// export\nexport default class EventService extends NbStoreService {\n /**\n * class constructor\n */\n constructor(config = {}) {\n super(config)\n }\n\n /**\n * logger function for overwrite\n */\n logger() {}\n\n //////////////////////////\n // PUBLIC METHODS //\n //////////////////////////\n\n /**\n * Register your evt handler, note we don't check the type here,\n * we expect you to be sensible and know what you are doing.\n * @param {string} evt name of event\n * @param {function} callback bind method --> if it's array or not\n * @param {object} [context=null] to execute this call in\n * @return {number} the size of the store\n */\n $on(evt , callback , context = null) {\n const type = 'on';\n this.validate(evt, callback)\n // first need to check if this evt is in lazy store\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register first then call later\n if (lazyStoreContent === false) {\n this.logger('($on)', `${evt} callback is not in lazy store`)\n // @TODO we need to check if there was other listener to this\n // event and are they the same type then we could solve that\n // register the different type to the same event name\n\n return this.addToNormalStore(evt, type, callback, context)\n }\n this.logger('($on)', `${evt} found in lazy store`)\n // this is when they call $trigger before register this callback\n let size = 0;\n lazyStoreContent.forEach(content => {\n let [ payload, ctx, t ] = content;\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.run(callback, payload, context || ctx)\n size += this.addToNormalStore(evt, type, callback, context || ctx)\n })\n return size;\n }\n\n /**\n * once only registered it once, there is no overwrite option here\n * @NOTE change in v1.3.0 $once can add multiple listeners\n * but once the event fired, it will remove this event (see $only)\n * @param {string} evt name\n * @param {function} callback to execute\n * @param {object} [context=null] the handler execute in\n * @return {boolean} result\n */\n $once(evt , callback , context = null) {\n this.validate(evt, callback)\n const type = 'once';\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register before call $trigger\n let nStore = this.normalStore;\n if (lazyStoreContent === false) {\n this.logger('($once)', `${evt} not in the lazy store`)\n // v1.3.0 $once now allow to add multiple listeners\n return this.addToNormalStore(evt, type, callback, context)\n } else {\n // now this is the tricky bit\n // there is a potential bug here that cause by the developer\n // if they call $trigger first, the lazy won't know it's a once call\n // so if in the middle they register any call with the same evt name\n // then this $once call will be fucked - add this to the documentation\n this.logger('($once)', lazyStoreContent)\n const list = Array.from(lazyStoreContent)\n // should never have more than 1\n const [ payload, ctx, t ] = list[0]\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.run(callback, payload, context || ctx)\n // remove this evt from store\n this.$off(evt)\n }\n }\n\n /**\n * This one event can only bind one callbackback\n * @param {string} evt event name\n * @param {function} callback event handler\n * @param {object} [context=null] the context the event handler execute in\n * @return {boolean} true bind for first time, false already existed\n */\n $only(evt, callback, context = null) {\n this.validate(evt, callback)\n const type = 'only';\n let added = false;\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register before call $trigger\n let nStore = this.normalStore;\n if (!nStore.has(evt)) {\n this.logger(`($only)`, `${evt} add to store`)\n added = this.addToNormalStore(evt, type, callback, context)\n }\n if (lazyStoreContent !== false) {\n // there are data store in lazy store\n this.logger('($only)', `${evt} found data in lazy store to execute`)\n const list = Array.from(lazyStoreContent)\n // $only allow to trigger this multiple time on the single handler\n list.forEach( l => {\n const [ payload, ctx, t ] = l;\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.run(callback, payload, context || ctx)\n })\n }\n return added;\n }\n\n /**\n * $only + $once this is because I found a very subtile bug when we pass a\n * resolver, rejecter - and it never fire because that's OLD adeed in v1.4.0\n * @param {string} evt event name\n * @param {function} callback to call later\n * @param {object} [context=null] exeucte context\n * @return {void}\n */\n $onlyOnce(evt, callback, context = null) {\n this.validate(evt, callback)\n const type = 'onlyOnce';\n let added = false;\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register before call $trigger\n let nStore = this.normalStore;\n if (!nStore.has(evt)) {\n this.logger(`($onlyOnce)`, `${evt} add to store`)\n added = this.addToNormalStore(evt, type, callback, context)\n }\n if (lazyStoreContent !== false) {\n // there are data store in lazy store\n this.logger('($onlyOnce)', lazyStoreContent)\n const list = Array.from(lazyStoreContent)\n // should never have more than 1\n const [ payload, ctx, t ] = list[0]\n if (t && t !== 'onlyOnce') {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.run(callback, payload, context || ctx)\n // remove this evt from store\n this.$off(evt)\n }\n return added;\n }\n\n /**\n * This is a shorthand of $off + $on added in V1.5.0\n * @param {string} evt event name\n * @param {function} callback to exeucte\n * @param {object} [context = null] or pass a string as type\n * @param {string} [type=on] what type of method to replace\n * @return {}\n */\n $replace(evt, callback, context = null, type = 'on') {\n if (this.validateType(type)) {\n this.$off(evt)\n let method = this['$' + type]\n return Reflect.apply(method, this, [evt, callback, context])\n }\n throw new Error(`${type} is not supported!`)\n }\n\n /**\n * trigger the event\n * @param {string} evt name NOT allow array anymore!\n * @param {mixed} [payload = []] pass to fn\n * @param {object|string} [context = null] overwrite what stored\n * @param {string} [type=false] if pass this then we need to add type to store too\n * @return {number} if it has been execute how many times\n */\n $trigger(evt , payload = [] , context = null, type = false) {\n this.validateEvt(evt)\n let found = 0;\n // first check the normal store\n let nStore = this.normalStore;\n this.logger('($trigger)', 'normalStore', nStore)\n if (nStore.has(evt)) {\n // @1.8.0 to add the suspend queue\n let added = this.$queue(evt, payload, context, type)\n this.logger('($trigger)', evt, 'found; add to queue: ', added)\n if (added === true) {\n return false; // not executed\n }\n let nSet = Array.from(nStore.get(evt))\n let ctn = nSet.length;\n let hasOnce = false;\n let hasOnly = false;\n for (let i=0; i < ctn; ++i) {\n ++found;\n // this.logger('found', found)\n let [ _, callback, ctx, type ] = nSet[i]\n this.run(callback, payload, context || ctx)\n if (type === 'once' || type === 'onlyOnce') {\n hasOnce = true;\n }\n }\n if (hasOnce) {\n nStore.delete(evt)\n }\n return found;\n }\n // now this is not register yet\n this.addToLazyStore(evt, payload, context, type)\n return found;\n }\n\n /**\n * this is an alias to the $trigger\n * @NOTE breaking change in V1.6.0 we swap the parameter around\n * @param {string} evt event name\n * @param {*} params pass to the callback\n * @param {string} type of call\n * @param {object} context what context callback execute in\n * @return {*} from $trigger\n */\n $call(evt, params, type = false, context = null) {\n let args = [evt, params]\n args.push(context, type)\n return Reflect.apply(this.$trigger, this, args)\n }\n\n /**\n * remove the evt from all the stores\n * @param {string} evt name\n * @return {boolean} true actually delete something\n */\n $off(evt) {\n this.validateEvt(evt)\n let stores = [ this.lazyStore, this.normalStore ]\n let found = false;\n stores.forEach(store => {\n if (store.has(evt)) {\n found = true;\n store.delete(evt)\n }\n })\n return found;\n }\n\n /**\n * return all the listener from the event\n * @param {string} evtName event name\n * @param {boolean} [full=false] if true then return the entire content\n * @return {array|boolean} listerner(s) or false when not found\n */\n $get(evt, full = false) {\n this.validateEvt(evt)\n let store = this.normalStore;\n if (store.has(evt)) {\n return Array\n .from(store.get(evt))\n .map( l => {\n if (full) {\n return l;\n }\n let [key, callback, ] = l;\n return callback;\n })\n }\n return false;\n }\n\n /**\n * store the return result from the run\n * @param {*} value whatever return from callback\n */\n set $done(value) {\n this.logger('($done)', 'value: ', value)\n if (this.keep) {\n this.result.push(value)\n } else {\n this.result = value;\n }\n }\n\n /**\n * @TODO is there any real use with the keep prop?\n * getter for $done\n * @return {*} whatever last store result\n */\n get $done() {\n if (this.keep) {\n this.logger('(get $done)', this.result)\n return this.result[this.result.length - 1]\n }\n return this.result;\n }\n\n\n}\n","// default\nimport NBEventService from './src/event-service'\n\nexport default NBEventService\n","// mapping the resolver to their respective nsp\n\nimport { JSONQL_PATH } from 'jsonql-constants'\nimport { groupByNamespace } from 'jsonql-jwt'\nimport { JsonqlResolverNotFoundError } from 'jsonql-errors'\n\nimport { MISSING_PROP_ERR } from './constants'\nimport getDebug from './get-debug'\nconst debug = getDebug('process-contract')\n\n/**\n * Just make sure the object contain what we are looking for\n * @param {object} opts configuration from checkOptions\n * @return {object} the target content\n */\nconst getResolverList = contract => {\n if (contract) {\n const { socket } = contract;\n if (socket) {\n return socket;\n }\n }\n throw new JsonqlResolverNotFoundError(MISSING_PROP_ERR)\n}\n\n/**\n * process the contract first\n * @param {object} opts configuration\n * @return {object} sorted list\n */\nexport default function processContract(opts) {\n const { contract, enableAuth } = opts;\n if (enableAuth) {\n return groupByNamespace(contract)\n }\n return {\n nspSet: { [JSONQL_PATH]: getResolverList(contract) },\n publicNamespace: JSONQL_PATH,\n size: 1 // this prop is pretty meaningless now\n }\n}\n","// export the util methods\nimport { QUERY_ARG_NAME, JS_WS_SOCKET_IO_NAME } from 'jsonql-constants'\nimport getNamespaceInOrder from './get-namespace-in-order'\nimport checkOptions from './check-options'\nimport ee from './ee'\nimport * as constants from './constants'\nimport getDebug from './get-debug'\n\nimport processContract from './process-contract'\nimport { isArray } from 'jsonql-params-validator'\n\nconst toArray = (arg) => isArray(arg) ? arg : [arg];\n\n/**\n * very simple tool to create the event name\n * @param {string} [...args] spread\n * @return {string} join by _\n */\nconst createEvt = (...args) => args.join('_')\n\n/**\n * Unbind the event\n * @param {object} ee EventEmitter\n * @param {string} namespace\n * @return {void}\n */\nconst clearMainEmitEvt = (ee, namespace) => {\n let nsps = isArray(namespace) ? namespace : [namespace]\n nsps.forEach(n => {\n ee.$off(createEvt(n, constants.EMIT_EVT))\n })\n}\n\n/**\n * @param {*} args arguments to send\n *@return {object} formatted payload\n */\nconst formatPayload = (args) => (\n { [QUERY_ARG_NAME]: args }\n)\n\n/**\n * @param {object} nsps namespace as key\n * @param {string} type of server\n */\nconst disconnect = (nsps, type = JS_WS_SOCKET_IO_NAME) => {\n try {\n const method = type === JS_WS_SOCKET_IO_NAME ? 'disconnect' : 'terminate';\n for (let namespace in nsps) {\n let nsp = nsps[namespace]\n if (nsp && nsp[method]) {\n Reflect.apply(nsp[method], null, [])\n }\n }\n } catch(e) {\n // socket.io throw a this.destroy of undefined?\n console.error('disconnect', e)\n }\n}\n\n\nexport {\n getNamespaceInOrder,\n createEvt,\n clearMainEmitEvt,\n checkOptions,\n ee,\n constants,\n getDebug,\n processContract,\n toArray,\n formatPayload,\n disconnect\n}\n","// @TODO port what is in the ws-main-handler\n// because all the client side call are via the ee\n// and that makes it re-usable between different client setup\nimport {\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME,\n EMIT_EVT,\n SOCKET_IO,\n WS\n} from './utils/constants'\nimport {\n LOGIN_EVENT_NAME,\n LOGOUT_EVENT_NAME,\n NOT_LOGIN_ERR_MSG,\n ERROR_PROP_NAME\n} from 'jsonql-constants'\n\nimport { getDebug, createEvt, clearMainEmitEvt } from './utils'\nimport triggerNamespacesOnError from './utils/trigger-namespaces-on-error'\nconst debugFn = getDebug('client-event-handler')\n\n/**\n * A fake ee handler\n * @param {string} namespace nsp\n * @param {object} ee EventEmitter\n * @return {void}\n */\nconst notLoginWsHandler = (namespace, ee) => {\n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function(resolverName, args) {\n debugFn('noLoginHandler hijack the ws call', namespace, resolverName, args)\n let error = {\n message: NOT_LOGIN_ERR_MSG\n }\n // It should just throw error here and should not call the result\n // because that's channel for handling normal event not the fake one\n ee.$call(createEvt(namespace, resolverName, ERROR_PROP_NAME), [error])\n // also trigger the result handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, RESULT_PROP_NAME), [{ error }])\n }\n )\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {array} namespaces namespace(s)\n * @param {object} ee Event Emitter instance\n * @param {function} bindWsHandler binding the ee to ws\n * @param {array} namespaces array of namespace available\n * @param {object} nsps namespaced nsp\n * @return {void} nothing\n */\nexport default function clientEventHandler(opts, nspMap, ee, bindWsHandler, namespaces, nsps) {\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run a waterfall here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n if (nsps[namespace]) {\n debugFn('call bindWsHandler', namespace)\n let args = [namespace, nsps[namespace], ee]\n if (opts.serverType === SOCKET_IO) {\n let { nspSet } = nspMap;\n args.push(nspSet[namespace])\n args.push(opts)\n }\n Reflect.apply(bindWsHandler, null, args)\n } else {\n // a dummy placeholder\n notLoginWsHandler(namespace, ee)\n }\n })\n // this will be available regardless enableAuth\n // because the server can log the client out\n ee.$on(LOGOUT_EVENT_NAME, function() {\n debugFn('LOGOUT_EVENT_NAME')\n // disconnect(nsps, opts.serverType)\n // we need to issue error to all the namespace onError handler\n triggerNamespacesOnError(ee, namespaces, LOGOUT_EVENT_NAME)\n // rebind all of the handler to the fake one\n namespaces.forEach( namespace => {\n clearMainEmitEvt(ee, namespace)\n // clear out the nsp\n nsps[namespace] = false;\n // add a NOT LOGIN error if call\n notLoginWsHandler(namespace, ee)\n })\n })\n}\n","// take the ws reply data for use\nimport { WS_EVT_NAME, WS_DATA_NAME, WS_REPLY_TYPE } from 'jsonql-constants'\nimport { isString, isKeyInObject } from 'jsonql-params-validator'\nimport { JsonqlError, clientErrorsHandler } from 'jsonql-errors'\n\nimport getDebug from '../utils/get-debug'\nconst debugFn = getDebug('extract-ws-payload')\n\nconst keys = [ WS_REPLY_TYPE, WS_EVT_NAME, WS_DATA_NAME ]\n\n/**\n * @param {object} payload should be string when reply but could be transformed\n * @return {boolean} true is OK\n */\nconst isWsReply = payload => {\n const { data } = payload;\n if (data) {\n let result = keys.filter(key => isKeyInObject(data, key))\n return (result.length === keys.length) ? data : false;\n }\n return false;\n}\n\n/**\n * @param {object} payload This is the entire ws Event Object\n * @return {object} false on failed\n */\nconst extractWsPayload = payload => {\n const { data } = payload;\n let json = isString(data) ? JSON.parse(data) : data;\n // debugFn('extractWsPayload', json)\n let fdata;\n if ((fdata = isWsReply(json)) !== false) {\n return {\n resolverName: fdata[WS_EVT_NAME],\n data: fdata[WS_DATA_NAME],\n type: fdata[WS_REPLY_TYPE]\n };\n }\n throw new JsonqlError('payload can not be decoded', payload)\n}\n// export it\nexport default extractWsPayload\n","// the WebSocket main handler\nimport {\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME,\n EMIT_EVT\n} from '../utils/constants'\nimport {\n ERROR_PROP_NAME,\n LOGIN_EVENT_NAME,\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_TYPE,\n READY_PROP_NAME\n} from 'jsonql-constants'\n\nimport extractWsPayload from './extract-ws-payload'\nimport { createQueryStr } from 'jsonql-params-validator'\n\nimport { getDebug, createEvt } from '../utils'\nconst debugFn = getDebug('ws-main-handler')\n\n/**\n * under extremely circumstances we might not even have a resolverName, then\n * we issue a global error for the developer to catch it\n * @param {object} ee event emitter\n * @param {string} namespace nsp\n * @param {string} resolverName resolver\n * @param {object} json decoded payload or error object\n */\nconst errorTypeHandler = (ee, namespace, resolverName, json) => {\n let evt = [namespace]\n if (resolverName) {\n debugFn(`a global error on ${namespace}`)\n evt.push(resolverName)\n }\n evt.push(ERROR_PROP_NAME)\n let evtName = Reflect.apply(createEvt, null, evt)\n // test if there is a data field\n let payload = json.data || json;\n ee.$trigger(evtName, [payload])\n}\n\n/**\n * Binding the even to socket normally\n * @param {string} namespace\n * @param {object} ws the nsp\n * @param {object} ee EventEmitter\n * @return {object} promise resolve after the onopen event\n */\nexport default function wsMainHandlerAction(namespace, ws, ee) {\n // send\n ws.onopen = function() {\n // we just call the onReady\n ee.$call(READY_PROP_NAME, namespace)\n // add listener\n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function(resolverName, args) {\n debugFn('calling server', resolverName, args)\n ws.send(\n createQueryStr(resolverName, args)\n )\n }\n )\n }\n\n // reply\n ws.onmessage = function(payload) {\n try {\n const json = extractWsPayload(payload)\n debugFn('Hear from server', json)\n const { resolverName, type } = json;\n switch (type) {\n case EMIT_REPLY_TYPE:\n let r = ee.$trigger(createEvt(namespace, resolverName, MESSAGE_PROP_NAME), [json])\n debugFn(MESSAGE_PROP_NAME, r)\n break;\n case ACKNOWLEDGE_REPLY_TYPE:\n debugFn(RESULT_PROP_NAME, json)\n let x = ee.$trigger(createEvt(namespace, resolverName, RESULT_PROP_NAME), [json])\n debugFn('onResult add to event?', x)\n break;\n case ERROR_TYPE:\n // this is handled error and we won't throw it\n // we need to extract the error from json\n errorTypeHandler(ee, namespace, resolverName, json)\n break;\n // @TODO there should be an error type instead of roll into the other two types? TBC\n default:\n // if this happen then we should throw it and halt the operation all together\n debugFn('Unhandled event!', json)\n errorTypeHandler(ee, namespace, resolverName, json)\n // let error = {error: {'message': 'Unhandled event!', type}};\n // ee.$trigger(createEvt(namespace, resolverName, RESULT_PROP_NAME), [error])\n }\n } catch(e) {\n errorTypeHandler(ee, namespace, false, e)\n }\n }\n // when the server close the connection\n ws.onclose = function() {\n debugFn('ws.onclose')\n // @TODO what to do with this\n // ee.$trigger(LOGOUT_EVENT_NAME, [namespace])\n }\n // listen to the LOGOUT_EVENT_NAME\n ee.$on(LOGOUT_EVENT_NAME, function close() {\n try {\n debugFn('terminate ws connection')\n ws.terminate()\n } catch(e) {\n debugFn('terminate ws error', e)\n }\n })\n}\n","// make this another standalone module\nimport { getNameFromPayload } from 'jsonql-params-validator'\nimport { LOGIN_EVENT_NAME, LOGOUT_EVENT_NAME, JS_WS_NAME } from 'jsonql-constants'\nimport { nspClient, nspAuthClient } from '../utils/create-nsp-client'\n// this become the cb\nimport clientEventHandler from '../client-event-handler'\nimport triggerNamespacesOnError from '../utils/trigger-namespaces-on-error'\n// move this up one level from client-event-handler\nimport wsMainHandler from './ws-main-handler'\nimport { getDebug, clearMainEmitEvt, getNamespaceInOrder, disconnect } from '../utils'\nconst debugFn = getDebug('ws-create-client')\n\n/**\n * Because the nsps can be throw away so it doesn't matter the scope\n * this will get reuse again\n * @param {object} opts configuration\n * @param {object} nspMap from contract\n * @param {string|null} token whether we have the token at run time\n * @return {object} nsps namespace with namespace as key\n */\nconst createNsps = function(opts, nspMap, token) {\n let { nspSet, publicNamespace } = nspMap;\n let login = false;\n let namespaces = [];\n let nsps = {};\n // first we need to binding all the events handler\n if (opts.enableAuth && opts.useJwt) {\n login = true; // just saying we need to listen to login event\n namespaces = getNamespaceInOrder(nspSet, publicNamespace)\n nsps = namespaces.map((namespace, i) => {\n if (i === 0) {\n if (token) {\n opts.token = token;\n return {[namespace]: nspAuthClient(namespace, opts)}\n }\n return {[namespace]: false}\n }\n return {[namespace]: nspClient(namespace, opts)}\n }).reduce((first, next) => Object.assign(first, next), {})\n } else {\n let namespace = getNameFromPayload(nspSet)\n namespaces.push(namespace)\n // standard without login\n // the stock version should not have a namespace\n nsps[namespace] = nspClient(false, opts)\n }\n // return\n return { nsps, namespaces, login }\n}\n\n/**\n * create a ws client\n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nexport default function createClient(opts, nspMap, ee) {\n // arguments that don't change\n let args = [opts, nspMap, ee, wsMainHandler]\n // now create the nsps\n let { nsps, namespaces, login } = createNsps(opts, nspMap, opts.token)\n // binding the listeners - and it will listen to LOGOUT event\n // to unbind itself, and the above call will bind it again\n Reflect.apply(clientEventHandler, null, args.concat([namespaces, nsps]))\n // setup listener\n if (login) {\n ee.$only(LOGIN_EVENT_NAME, function(token) {\n disconnect(nsps, JS_WS_NAME)\n // @TODO should we trigger error on this one?\n // triggerNamespacesOnError(ee, namespaces, LOGIN_EVENT_NAME)\n clearMainEmitEvt(ee, namespaces)\n debugFn('LOGIN_EVENT_NAME', token)\n let newNsps = createNsps(opts, nspMap, token)\n // rebind it\n Reflect.apply(\n clientEventHandler,\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\n }\n // return what input\n return { opts, nspMap, ee }\n}\n","// we only need to export one interface from now on\n\nimport createClient from './create-client'\n\nexport default createClient\n","// this will create the socket.io client\nimport { chainPromises } from 'jsonql-jwt'\nimport { getNameFromPayload, isString } from 'jsonql-params-validator'\nimport { LOGIN_EVENT_NAME, LOGOUT_EVENT_NAME } from 'jsonql-constants'\n\nimport { nspClient, nspAuthClient } from '../utils/create-nsp-client'\nimport clientEventHandler from '../client-event-handler'\nimport ioMainHandler from './io-main-handler'\n\nimport { getDebug, clearMainEmitEvt, getNamespaceInOrder, disconnect } from '../utils'\nconst debugFn = getDebug('io-create-client')\n\n// just to make it less ugly\nconst mapNsps = (nsps, namespaces) => nsps\n .map((nsp, i) => ({[namespaces[i]]: nsp}))\n .reduce((last, next) => Object.assign(last,next), {})\n\n/**\n * This one will run the create nsps in sequence and make sure\n * the auth one connect before we call the others\n * @param {object} opts configuration\n * @param {object} nspMap contract map\n * @param {string} token validation\n * @return {object} promise resolve with namespaces, nsps in same order array\n */\nconst createAuthNsps = function(opts, nspMap, token, namespaces) {\n let { publicNamespace } = nspMap;\n opts.token = token;\n let p1 = () => nspAuthClient(namespaces[0], opts)\n let p2 = () => nspClient(namespaces[1], opts)\n return chainPromises([p1(), p2()])\n .then(nsps => ({\n nsps: mapNsps(nsps, namespaces),\n namespaces,\n login: false\n }))\n}\n\n/**\n * Because the nsps can be throw away so it doesn't matter the scope\n * this will get reuse again\n * @param {object} opts configuration\n * @param {object} nspMap from contract\n * @param {string|null} token whether we have the token at run time\n * @return {object} nsps namespace with namespace as key\n */\nconst createNsps = function(opts, nspMap, token) {\n let { nspSet, publicNamespace } = nspMap;\n let login = false;\n let nsps = {}\n // first we need to binding all the events handler\n if (opts.enableAuth && opts.useJwt) {\n let namespaces = getNamespaceInOrder(nspSet, publicNamespace)\n debugFn('namespaces', namespaces)\n login = opts.useJwt; // just saying we need to listen to login event\n if (token) {\n debugFn('call createAuthNsps')\n return createAuthNsps(opts, nspMap, token, namespaces)\n }\n debugFn('init with a placeholder')\n return nspClient(publicNamespace, opts)\n .then(nsp => ({\n nsps: {\n [ publicNamespace ]: nsp,\n [ namespaces[0] ]: false\n },\n namespaces,\n login\n }))\n }\n // standard without login\n // the stock version should not have a namespace\n return nspClient(false, opts)\n .then(nsp => ({\n nsps: {[publicNamespace]: nsp},\n namespaces: [publicNamespace],\n login\n }))\n}\n\n\n\n/**\n * This is just copy of the ws version we need to figure\n * out how to deal with the roundtrip login later\n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nexport default function createClient(opts, nspMap, ee) {\n // arguments don't change\n let args = [opts, nspMap, ee, ioMainHandler]\n return createNsps(opts, nspMap, opts.token)\n .then( ({ nsps, namespaces, login }) => {\n // binding the listeners - and it will listen to LOGOUT event\n // to unbind itself, and the above call will bind it again\n Reflect.apply(clientEventHandler, null, args.concat([namespaces, nsps]))\n if (login) {\n ee.$only(LOGIN_EVENT_NAME, function(token) {\n // here we should disconnect all the previous nsps\n disconnect(nsps)\n // first trigger a LOGOUT event to unbind ee to ws\n // ee.$trigger(LOGOUT_EVENT_NAME) // <-- this seems to cause a lot of problems\n clearMainEmitEvt(ee, namespaces)\n debugFn('LOGIN_EVENT_NAME')\n createNsps(opts, nspMap, token)\n .then(newNsps => {\n // rebind it\n Reflect.apply(\n clientEventHandler,\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\n })\n }\n // return this will also works because the outter call are in promise chain\n return { opts, nspMap, ee }\n })\n}\n","// generator resolvers\n// this will be a mini client server architect\n// The reason is when the enableAuth setup - the private route\n// might not be validated, but we need the callable point is ready\n// therefore this part will always take the contract and generate\n// callable api for the developer to setup their front end\n// the only thing is - when they call they might get an error or\n// NOT_LOGIN_IN and they can react to this error accordingly\nimport {\n JsonqlResolverNotFoundError,\n JsonqlValidationError,\n JsonqlError,\n finalCatch\n} from 'jsonql-errors'\nimport {\n validateAsync,\n validateSync,\n isKeyInObject,\n isString\n} from 'jsonql-params-validator'\nimport {\n ERROR_TYPE,\n DATA_KEY,\n ERROR_KEY,\n ERROR_PROP_NAME,\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME,\n SEND_MSG_PROP_NAME,\n LOGIN_EVENT_NAME,\n READY_PROP_NAME,\n LOGOUT_EVENT_NAME\n} from 'jsonql-constants'\nimport { getDebug, constants, createEvt, toArray } from './utils'\nconst { EMIT_EVT, NOT_ALLOW_OP, UNKNOWN_RESULT, MY_NAMESPACE } = constants;\nconst debugFn = getDebug('generator')\n\n/**\n * prepare the methods\n * @param {object} opts configuration\n * @param {object} nspMap resolvers index by their namespace\n * @param {object} ee EventEmitter\n * @return {object} of resolvers\n * @public\n */\nexport default function generator(opts, nspMap, ee) {\n const obj = {};\n const { nspSet } = nspMap;\n for (let namespace in nspSet) {\n let list = nspSet[namespace]\n for (let resolverName in list) {\n let params = list[resolverName]\n let fn = createResolver(ee, namespace, resolverName, params)\n obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n }\n }\n // add error handler\n createNamespaceErrorHandler(obj, ee, nspSet)\n // add onReady handler\n createOnReadyhandler(obj, ee, nspSet)\n // Auth related methods\n createAuthMethods(obj, ee, opts)\n // this is a helper method for the developer to know the namespace inside\n obj.getNsp = () => {\n return Object.keys(nspSet)\n }\n // output\n return obj;\n}\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @return {function} resolver\n */\nfunction createResolver(ee, namespace, resolverName, params) {\n // note we pass the new withResult=true option\n return function(...args) {\n return validateAsync(args, params.params, true)\n .then( _args => actionCall(ee, namespace, resolverName, _args) )\n .catch(finalCatch)\n }\n}\n\n/**\n * just wrapper\n * @param {object} ee EventEmitter\n * @param {string} namespace where this belongs\n * @param {string} resolverName resolver\n * @param {array} args arguments\n * @return {void} nothing\n */\nfunction actionCall(ee, namespace, resolverName, args = []) {\n debugFn(`actionCall: ${namespace} ${resolverName}`, args)\n ee.$trigger(createEvt(namespace, EMIT_EVT), [\n resolverName,\n toArray(args)\n ])\n}\n\n/**\n * break out to use in different places to handle the return from server\n * @param {object} data from server\n * @param {function} resolver from promise\n * @param {function} rejecter from promise\n * @return {void} nothing\n */\nfunction respondHandler(data, resolver, rejecter) {\n if (isKeyInObject(data, 'error')) {\n debugFn('rejecter called', data.error)\n rejecter(data.error)\n } else if (isKeyInObject(data, 'data')) {\n debugFn('resolver called', data.data)\n resolver(data.data)\n } else {\n debugFn('UNKNOWN_RESULT', data)\n rejecter({message: UNKNOWN_RESULT, error: data})\n }\n}\n\n/**\n * Add extra property to the resolver\n * @param {string} namespace where this belongs\n * @param {string} resolverName name as event name\n * @param {object} params from contract\n * @param {function} fn resolver function\n * @param {object} ee EventEmitter\n * @return {function} resolver\n */\nconst setupResolver = (namespace, resolverName, params, fn, ee) => {\n // also need to setup a getter to get back the namespace of this resolver\n if (Object.getOwnPropertyDescriptor(fn, MY_NAMESPACE) === undefined) {\n Object.defineProperty(fn, MY_NAMESPACE, {\n value: namespace,\n writeable: false\n })\n }\n // onResult handler\n if (Object.getOwnPropertyDescriptor(fn, RESULT_PROP_NAME) === undefined) {\n Object.defineProperty(fn, RESULT_PROP_NAME, {\n set: function(resultCallback) {\n if (typeof resultCallback === 'function') {\n ee.$only(\n createEvt(namespace, resolverName, RESULT_PROP_NAME),\n function resultHandler(result) {\n respondHandler(result, resultCallback, (error) => {\n ee.$trigger(createEvt(namespace, resolverName, ERROR_PROP_NAME), error)\n })\n }\n )\n }\n },\n get: function() {\n return null;\n }\n })\n }\n // we do need to add the send prop back because it's the only way to deal with\n // bi-directional data stream\n if (Object.getOwnPropertyDescriptor(fn, MESSAGE_PROP_NAME) === undefined) {\n Object.defineProperty(fn, MESSAGE_PROP_NAME, {\n set: function(messageCallback) {\n // we expect this to be a function\n if (typeof messageCallback === 'function') {\n // did that add to the callback\n let onMessageCallback = (args) => {\n respondHandler(args, messageCallback, (error) => {\n ee.$trigger(createEvt(namespace, resolverName, ERROR_PROP_NAME), error)\n })\n }\n // register the handler for this message event\n ee.$only(createEvt(namespace, resolverName, MESSAGE_PROP_NAME), onMessageCallback)\n }\n },\n get: function() {\n return null; // just return nothing\n }\n })\n }\n // add an ERROR_PROP_NAME handler\n if (Object.getOwnPropertyDescriptor(fn, ERROR_PROP_NAME) === undefined) {\n Object.defineProperty(fn, ERROR_PROP_NAME, {\n set: function(resolverErrorHandler) {\n if (typeof resolverErrorHandler === 'function') {\n // please note ERROR_PROP_NAME can add multiple listners\n ee.$only(createEvt(namespace, resolverName, ERROR_PROP_NAME), resolverErrorHandler)\n }\n },\n get: function() {\n return null;\n }\n })\n }\n // pairing with the server vesrion SEND_MSG_PROP_NAME\n if (Object.getOwnPropertyDescriptor(fn, SEND_MSG_PROP_NAME) === undefined) {\n Object.defineProperty(fn, SEND_MSG_PROP_NAME, {\n set: function(messagePayload) {\n const result = validateSync(toArray(messagePayload), params.params, true)\n // here is the different we don't throw erro instead we trigger an\n // onError\n if (result[ERROR_KEY] && result[ERROR_KEY].length) {\n ee.$call(\n createEvt(namespace, resolverName, ERROR_PROP_NAME),\n [JsonqlValidationError(resolverName, result[ERROR_KEY])]\n )\n } else {\n // there is no return only an action call\n actionCall(ee, namespace, resolverName, result[DATA_KEY])\n }\n },\n get: function() {\n return null; // just return nothing\n }\n })\n }\n return fn;\n}\n\n/**\n * The problem is the namespace can have more than one\n * and we only have on onError message\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @param {object} nspSet namespace keys\n * @return {void}\n */\nconst createNamespaceErrorHandler = (obj, ee, nspSet) => {\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the obj itself\n if (Object.getOwnPropertyDescriptor(obj, ERROR_PROP_NAME) === undefined) {\n Object.defineProperty(obj, ERROR_PROP_NAME, {\n set: function(namespaceErrorHandler) {\n if (typeof namespaceErrorHandler === 'function') {\n // please note ERROR_PROP_NAME can add multiple listners\n for (let namespace in nspSet) {\n // this one is very tricky, we need to make sure the trigger is calling\n // with the namespace as well as the error\n ee.$on(createEvt(namespace, ERROR_PROP_NAME), namespaceErrorHandler)\n }\n }\n },\n get: function() {\n return null;\n }\n })\n }\n}\n\n/**\n * This event will fire when the socket.io.on('connection') and ws.onopen\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @param {object} nspSet namespace keys\n * @return {void}\n */\nconst createOnReadyhandler = (obj, ee, nspSet) => {\n if (Object.getOwnPropertyDescriptor(obj, READY_PROP_NAME) === undefined) {\n Object.defineProperty(obj, READY_PROP_NAME, {\n set: function(onReadyCallback) {\n if (typeof onReadyCallback === 'function') {\n // reduce it down to just one flat level\n let result = ee.$on(READY_PROP_NAME, onReadyCallback)\n }\n },\n get: function() {\n return null;\n }\n })\n }\n}\n\n/**\n * Create auth related methods\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @param {object} opts configuration\n * @return {void}\n */\nconst createAuthMethods = (obj, ee, opts) => {\n if (opts.enableAuth) {\n // create an additonal login handler\n // we require the token\n obj[opts.loginHandlerName] = (token) => {\n debugFn(opts.loginHandlerName, token)\n if (token && isString(token)) {\n return ee.$trigger(LOGIN_EVENT_NAME, [token])\n }\n throw new JsonqlValidationError(opts.loginHandlerName)\n }\n // logout event handler\n obj[opts.logoutHandlerName] = (...args) => {\n ee.$trigger(LOGOUT_EVENT_NAME, args)\n }\n }\n}\n","// main api to get the ws-client\n\nimport createSocketClient from './create-socket-client'\nimport generator from './generator'\n\nimport { checkOptions, ee, processContract } from './utils'\n\n/**\n * The main interface to create the wsClient for use\n * @param {function} clientGenerator this is an internal way to generate node or browser client\n * @return {function} wsClient\n * @public\n */\nexport default function main(clientGenerator) {\n /**\n * @param {object} config configuration\n * @param {object} [eventEmitter=false] this will be the bridge between clients\n * @return {object} wsClient\n */\n const wsClient = (config, eventEmitter = false) => {\n return checkOptions(config)\n .then(opts => ({\n opts,\n nspMap: processContract(opts),\n ee: eventEmitter || new ee()\n })\n )\n .then(clientGenerator)\n .then(\n ({ opts, nspMap, ee }) => createSocketClient(opts, nspMap, ee)\n )\n .then(\n ({ opts, nspMap, ee }) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error('jsonql-ws-client init error', err)\n })\n }\n // use the Object.addProperty trick\n Object.defineProperty(wsClient, 'CLIENT_TYPE_INFO', {\n value: '__PLACEHOLDER__',\n writable: false\n })\n return wsClient;\n}\n","// This is the module entry point\nimport clientGenerator from './src/utils/client-generator'\nimport main from './src/main'\n\nexport default main(clientGenerator)\n"],"names":[],"mappings":";;;;;;;;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;ECAA;;;;;;;;;;;ECAA;;;;;;;;;ECAA;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAA;;;;;;;;;;"} \ No newline at end of file diff --git a/packages/ws-client/package.json b/packages/ws-client/package.json index 1d0f8361..7aad0580 100755 --- a/packages/ws-client/package.json +++ b/packages/ws-client/package.json @@ -46,39 +46,41 @@ "author": "Joel Chu ", "license": "MIT", "devDependencies": { - "ava": "^2.1.0", + "ava": "^2.2.0", "debug": "^4.1.1", "esm": "^3.2.25", - "fs-extra": "^8.0.1", + "fs-extra": "^8.1.0", "glob": "^7.1.4", - "jsonql-contract": "^1.5.6", - "jsonql-koa": "^1.2.3", - "jsonql-ws-server": "^1.1.0", + "jsonql-contract": "^1.7.7", + "jsonql-koa": "^1.3.7", + "jsonql-ws-server": "^1.2.0", "koa": "^2.7.0", "koa-bodyparser": "^4.2.1", - "rollup": "^1.16.2", + "rollup": "^1.19.4", "rollup-plugin-alias": "^1.5.2", "rollup-plugin-async": "^1.2.0", - "rollup-plugin-buble": "^0.19.6", + "rollup-plugin-buble": "^0.19.8", "rollup-plugin-bundle-size": "^1.0.3", - "rollup-plugin-commonjs": "^10.0.0", - "rollup-plugin-copy": "^3.0.0", + "rollup-plugin-commonjs": "^10.0.2", + "rollup-plugin-copy": "^3.1.0", "rollup-plugin-json": "^4.0.0", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", - "rollup-plugin-node-resolve": "^5.1.0", + "rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-replace": "^2.2.0", "rollup-plugin-serve": "^1.0.1", - "rollup-plugin-terser": "^5.0.0", + "rollup-plugin-terser": "^5.1.1", "rollup-pluginutils": "^2.8.1", - "server-io-core": "^1.0.12", - "sorcery": "^0.10.0" + "server-io-core": "^1.2.0", + "sorcery": "^0.10.0", + "ws": "^7.1.2" }, "ava": { "files": [ "tests/*.test.js", "!tests/helpers/*.*", - "!tests/fixtures/*.*" + "!tests/fixtures/*.*", + "!tests/jwt/*.*" ], "require": [ "esm" @@ -94,12 +96,12 @@ "node": ">=8" }, "dependencies": { - "jsonql-constants": "^1.7.4", - "jsonql-errors": "^1.0.9", - "jsonql-jwt": "^1.2.1", - "jsonql-params-validator": "^1.4.2", + "jsonql-constants": "^1.7.9", + "jsonql-errors": "^1.1.1", + "jsonql-jwt": "^1.2.5", + "jsonql-params-validator": "^1.4.3", "kefir": "^3.8.6", - "nb-event-service": "^1.6.0" + "nb-event-service": "^1.8.3" }, "repository": { "type": "git", diff --git a/packages/ws-client/src/node/client-generator.js b/packages/ws-client/src/node/client-generator.js index c5e61ff9..48edb54b 100644 --- a/packages/ws-client/src/node/client-generator.js +++ b/packages/ws-client/src/node/client-generator.js @@ -4,12 +4,15 @@ const { socketIoNodeHandshakeLogin, socketIoNodeRoundtripLogin, - socketIoNodeClientAsync, - chainPromises, + socketIoNodeClientAsync +} = require('./socketio-client') + +const { wsNodeClient, wsNodeAuthClient -} = require('jsonql-jwt') +} = require('./ws-client') +const { chainPromises } = require('jsonql-jwt') const { JsonqlError } = require('jsonql-errors') const { JS_WS_SOCKET_IO_NAME, JS_WS_NAME } = require('jsonql-constants') diff --git a/packages/ws-client/src/node/main.cjs.js b/packages/ws-client/src/node/main.cjs.js index b8b7ad9f..9903c94b 100644 --- a/packages/ws-client/src/node/main.cjs.js +++ b/packages/ws-client/src/node/main.cjs.js @@ -446,7 +446,7 @@ var JS_WS_NAME = 'ws'; var MESSAGE_PROP_NAME = 'onMessage'; var RESULT_PROP_NAME = 'onResult'; var ERROR_PROP_NAME = 'onError'; -var READY_PROP_NAME = 'onReady'; +var READY_PROP_NAME = 'onReady'; var SEND_MSG_PROP_NAME = 'send'; var NOT_LOGIN_ERR_MSG = 'NOT LOGIN'; var HSA_ALGO = 'HS256'; @@ -4078,7 +4078,7 @@ function isArrayLikeObject(value) { } /** - * Gets the value at `key`, unless `key` is "__proto__". + * Gets the value at `key`, unless `key` is "__proto__" or "constructor". * * @private * @param {Object} object The object to query. @@ -4086,6 +4086,10 @@ function isArrayLikeObject(value) { * @returns {*} Returns the property value. */ function safeGet(object, key) { + if (key === 'constructor' && typeof object[key] === 'function') { + return; + } + if (key == '__proto__') { return; } @@ -4214,8 +4218,8 @@ function baseMerge(object, source, srcIndex, customizer, stack) { return; } baseFor(source, function(srcValue, key) { + stack || (stack = new Stack); if (isObject(srcValue)) { - stack || (stack = new Stack); baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); } else { @@ -5591,21 +5595,31 @@ function getNameFromPayload(payload) { /** * @param {string} resolverName name of function * @param {array} [args=[]] from the ...args + * @param {boolean} [jsonp = false] add v1.3.0 to koa * @return {object} formatted argument */ -function createQuery(resolverName, args) { - var obj, obj$1; +function createQuery(resolverName, args, jsonp) { + var obj; if ( args === void 0 ) args = []; + if ( jsonp === void 0 ) jsonp = false; if (checkIsString(resolverName) && checkIsArray(args)) { - return ( obj$1 = {}, obj$1[resolverName] = ( obj = {}, obj[QUERY_ARG_NAME] = args, obj ), obj$1 ) + var payload = {}; + payload[QUERY_ARG_NAME] = args; + if (jsonp === true) { + return payload; + } + return ( obj = {}, obj[resolverName] = payload, obj ) } throw new JsonqlValidationError("[createQuery] expect resolverName to be string and args to be array!", { resolverName: resolverName, args: args }) } // string version of the above -function createQueryStr(resolverName, args) { - return JSON.stringify(createQuery(resolverName, args)) +function createQueryStr(resolverName, args, jsonp) { + if ( args === void 0 ) args = []; + if ( jsonp === void 0 ) jsonp = false; + + return JSON.stringify(createQuery(resolverName, args, jsonp)) } // export @@ -5779,630 +5793,763 @@ function hashCode(s) { return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0) } -// this is the new implementation without the hash key -// export -var EventService = function EventService(config) { - if ( config === void 0 ) config = {}; - - if (config.logger && typeof config.logger === 'function') { - this.logger = config.logger; - } - this.keep = config.keep; - // for the $done setter - this.result = config.keep ? [] : null; - // we need to init the store first otherwise it could be a lot of checking later - this.normalStore = new Map(); - this.lazyStore = new Map(); +// making all the functionality on it's own +// import { WatchClass } from './watch' + +var SuspendClass = function SuspendClass() { + // suspend, release and queue + this.__suspend__ = null; + this.queueStore = new Set(); + /* + this.watch('suspend', function(value, prop, oldValue) { + this.logger(`${prop} set from ${oldValue} to ${value}`) + // it means it set the suspend = true then release it + if (oldValue === true && value === false) { + // we want this happen after the return happens + setTimeout(() => { + this.release() + }, 1) + } + return value; // we need to return the value to store it + }) + */ }; -var prototypeAccessors = { $done: { configurable: true },normalStore: { configurable: true },lazyStore: { configurable: true } }; - -/** - * logger function for overwrite - */ -EventService.prototype.logger = function logger () {}; - -////////////////////////// -// PUBLIC METHODS // -////////////////////////// +var prototypeAccessors = { $suspend: { configurable: true },$queues: { configurable: true } }; /** - * Register your evt handler, note we don't check the type here, - * we expect you to be sensible and know what you are doing. - * @param {string} evt name of event - * @param {function} callback bind method --> if it's array or not - * @param {object} [context=null] to execute this call in - * @return {number} the size of the store + * setter to set the suspend and check if it's boolean value + * @param {boolean} value to trigger */ -EventService.prototype.$on = function $on (evt , callback , context) { +prototypeAccessors.$suspend.set = function (value) { var this$1 = this; - if ( context === void 0 ) context = null; - var type = 'on'; - this.validate(evt, callback); - // first need to check if this evt is in lazy store - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register first then call later - if (lazyStoreContent === false) { - this.logger('$on', (evt + " callback is not in lazy store")); - // @TODO we need to check if there was other listener to this - // event and are they the same type then we could solve that - // register the different type to the same event name - - return this.addToNormalStore(evt, type, callback, context) - } - this.logger('$on', (evt + " found in lazy store")); - // this is when they call $trigger before register this callback - var size = 0; - lazyStoreContent.forEach(function (content) { - var payload = content[0]; - var ctx = content[1]; - var t = content[2]; - if (t && t !== type) { - throw new Error(("You are trying to register an event already been taken by other type: " + t)) + if (typeof value === 'boolean') { + var lastValue = this.__suspend__; + this.__suspend__ = value; + this.logger('($suspend)', ("Change from " + lastValue + " --> " + value)); + if (lastValue === true && value === false) { + setTimeout(function () { + this$1.release(); + }, 1); } - this$1.run(callback, payload, context || ctx); - size += this$1.addToNormalStore(evt, type, callback, context || ctx); - }); - return size; -}; - -/** - * once only registered it once, there is no overwrite option here - * @NOTE change in v1.3.0 $once can add multiple listeners - * but once the event fired, it will remove this event (see $only) - * @param {string} evt name - * @param {function} callback to execute - * @param {object} [context=null] the handler execute in - * @return {boolean} result - */ -EventService.prototype.$once = function $once (evt , callback , context) { - if ( context === void 0 ) context = null; - - this.validate(evt, callback); - var type = 'once'; - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register before call $trigger - var nStore = this.normalStore; - if (lazyStoreContent === false) { - this.logger('$once', (evt + " not in the lazy store")); - // v1.3.0 $once now allow to add multiple listeners - return this.addToNormalStore(evt, type, callback, context) } else { - // now this is the tricky bit - // there is a potential bug here that cause by the developer - // if they call $trigger first, the lazy won't know it's a once call - // so if in the middle they register any call with the same evt name - // then this $once call will be fucked - add this to the documentation - this.logger('$once', lazyStoreContent); - var list = Array.from(lazyStoreContent); - // should never have more than 1 - var ref = list[0]; - var payload = ref[0]; - var ctx = ref[1]; - var t = ref[2]; - if (t && t !== type) { - throw new Error(("You are trying to register an event already been taken by other type: " + t)) - } - this.run(callback, payload, context || ctx); - // remove this evt from store - this.$off(evt); + throw new Error("$suspend only accept Boolean value!") } }; /** - * This one event can only bind one callbackback - * @param {string} evt event name - * @param {function} callback event handler - * @param {object} [context=null] the context the event handler execute in - * @return {boolean} true bind for first time, false already existed + * queuing call up when it's in suspend mode + * @param {any} value + * @return {Boolean} true when added or false when it's not */ -EventService.prototype.$only = function $only (evt, callback, context) { - var this$1 = this; - if ( context === void 0 ) context = null; +SuspendClass.prototype.$queue = function $queue () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; - this.validate(evt, callback); - var type = 'only'; - var added = false; - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register before call $trigger - var nStore = this.normalStore; - if (!nStore.has(evt)) { - this.logger("$only", (evt + " add to store")); - added = this.addToNormalStore(evt, type, callback, context); - } - if (lazyStoreContent !== false) { - // there are data store in lazy store - this.logger('$only', (evt + " found data in lazy store to execute")); - var list = Array.from(lazyStoreContent); - // $only allow to trigger this multiple time on the single handler - list.forEach( function (l) { - var payload = l[0]; - var ctx = l[1]; - var t = l[2]; - if (t && t !== type) { - throw new Error(("You are trying to register an event already been taken by other type: " + t)) - } - this$1.run(callback, payload, context || ctx); - }); + if (this.__suspend__ === true) { + this.logger('($queue)', 'added to $queue', args); + // there shouldn't be any duplicate ... + this.queueStore.add(args); } - return added; + return this.__suspend__; }; /** - * $only + $once this is because I found a very subtile bug when we pass a - * resolver, rejecter - and it never fire because that's OLD adeed in v1.4.0 - * @param {string} evt event name - * @param {function} callback to call later - * @param {object} [context=null] exeucte context - * @return {void} + * a getter to get all the store queue + * @return {array} Set turn into Array before return */ -EventService.prototype.$onlyOnce = function $onlyOnce (evt, callback, context) { - if ( context === void 0 ) context = null; - - this.validate(evt, callback); - var type = 'onlyOnce'; - var added = false; - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register before call $trigger - var nStore = this.normalStore; - if (!nStore.has(evt)) { - this.logger("$onlyOnce", (evt + " add to store")); - added = this.addToNormalStore(evt, type, callback, context); - } - if (lazyStoreContent !== false) { - // there are data store in lazy store - this.logger('$onlyOnce', lazyStoreContent); - var list = Array.from(lazyStoreContent); - // should never have more than 1 - var ref = list[0]; - var payload = ref[0]; - var ctx = ref[1]; - var t = ref[2]; - if (t && t !== 'onlyOnce') { - throw new Error(("You are trying to register an event already been taken by other type: " + t)) - } - this.run(callback, payload, context || ctx); - // remove this evt from store - this.$off(evt); +prototypeAccessors.$queues.get = function () { + var size = this.queueStore.size; + this.logger('($queues)', ("size: " + size)); + if (size > 0) { + return Array.from(this.queueStore) } - return added; + return [] }; /** - * This is a shorthand of $off + $on added in V1.5.0 - * @param {string} evt event name - * @param {function} callback to exeucte - * @param {object} [context = null] or pass a string as type - * @param {string} [type=on] what type of method to replace - * @return {} + * Release the queue + * @return {int} size if any */ -EventService.prototype.$replace = function $replace (evt, callback, context, type) { - if ( context === void 0 ) context = null; - if ( type === void 0 ) type = 'on'; +SuspendClass.prototype.release = function release () { + var this$1 = this; - if (this.validateType(type)) { - this.$off(evt); - var method = this['$' + type]; - return Reflect.apply(method, this, [evt, callback, context]) + var size = this.queueStore.size; + this.logger('(release)', ("Release was called " + size)); + if (size > 0) { + var queue = Array.from(this.queueStore); + this.queueStore.clear(); + this.logger('queue', queue); + queue.forEach(function (args) { + this$1.logger(args); + Reflect.apply(this$1.$trigger, this$1, args); + }); + this.logger(("Release size " + (this.queueStore.size))); } - throw new Error((type + " is not supported!")) }; -/** - * trigger the event - * @param {string} evt name NOT allow array anymore! - * @param {mixed} [payload = []] pass to fn - * @param {object|string} [context = null] overwrite what stored - * @param {string} [type=false] if pass this then we need to add type to store too - * @return {number} if it has been execute how many times - */ -EventService.prototype.$trigger = function $trigger (evt , payload , context, type) { - if ( payload === void 0 ) payload = []; - if ( context === void 0 ) context = null; - if ( type === void 0 ) type = false; +Object.defineProperties( SuspendClass.prototype, prototypeAccessors ); - this.validateEvt(evt); - var found = 0; - // first check the normal store - var nStore = this.normalStore; - this.logger('$trigger', nStore); - if (nStore.has(evt)) { - this.logger('$trigger', evt, 'found'); - var nSet = Array.from(nStore.get(evt)); - var ctn = nSet.length; - var hasOnce = false; - for (var i=0; i < ctn; ++i) { - ++found; - // this.logger('found', found) - var ref = nSet[i]; - var _ = ref[0]; - var callback = ref[1]; - var ctx = ref[2]; - var type$1 = ref[3]; - this.run(callback, payload, context || ctx); - if (type$1 === 'once' || type$1 === 'onlyOnce') { - hasOnce = true; - } - } - if (hasOnce) { - nStore.delete(evt); - } - return found; - } - // now this is not register yet - this.addToLazyStore(evt, payload, context, type); - return found; -}; +// break up the main file because its getting way too long -/** - * this is an alias to the $trigger - * @NOTE breaking change in V1.6.0 we swap the parameter around - * @param {string} evt event name - * @param {*} params pass to the callback - * @param {string} type of call - * @param {object} context what context callback execute in - * @return {*} from $trigger - */ -EventService.prototype.$call = function $call (evt, params, type, context) { - if ( type === void 0 ) type = false; - if ( context === void 0 ) context = null; - - var args = [evt, params]; - args.push(context, type); - return Reflect.apply(this.$trigger, this, args) -}; +var NbEventServiceBase = /*@__PURE__*/(function (SuspendClass) { + function NbEventServiceBase(config) { + if ( config === void 0 ) config = {}; -/** - * remove the evt from all the stores - * @param {string} evt name - * @return {boolean} true actually delete something - */ -EventService.prototype.$off = function $off (evt) { - this.validateEvt(evt); - var stores = [ this.lazyStore, this.normalStore ]; - var found = false; - stores.forEach(function (store) { - if (store.has(evt)) { - found = true; - store.delete(evt); + SuspendClass.call(this); + if (config.logger && typeof config.logger === 'function') { + this.logger = config.logger; } - }); - return found; -}; - -/** - * return all the listener from the event - * @param {string} evtName event name - * @param {boolean} [full=false] if true then return the entire content - * @return {array|boolean} listerner(s) or false when not found - */ -EventService.prototype.$get = function $get (evt, full) { - if ( full === void 0 ) full = false; - - this.validateEvt(evt); - var store = this.normalStore; - if (store.has(evt)) { - return Array - .from(store.get(evt)) - .map( function (l) { - if (full) { - return l; - } - var key = l[0]; - var callback = l[1]; - return callback; - }) + this.keep = config.keep; + // for the $done setter + this.result = config.keep ? [] : null; + // we need to init the store first otherwise it could be a lot of checking later + this.normalStore = new Map(); + this.lazyStore = new Map(); } - return false; -}; -/** - * store the return result from the run - * @param {*} value whatever return from callback - */ -prototypeAccessors.$done.set = function (value) { - this.logger('set $done', value); - if (this.keep) { - this.result.push(value); - } else { - this.result = value; - } -}; + if ( SuspendClass ) NbEventServiceBase.__proto__ = SuspendClass; + NbEventServiceBase.prototype = Object.create( SuspendClass && SuspendClass.prototype ); + NbEventServiceBase.prototype.constructor = NbEventServiceBase; -/** - * @TODO is there any real use with the keep prop? - * getter for $done - * @return {*} whatever last store result - */ -prototypeAccessors.$done.get = function () { - if (this.keep) { - this.logger(this.result); - return this.result[this.result.length - 1] - } - return this.result; -}; + var prototypeAccessors = { normalStore: { configurable: true },lazyStore: { configurable: true } }; -///////////////////////////// -// PRIVATE METHODS // -///////////////////////////// + /** + * validate the event name(s) + * @param {string[]} evt event name + * @return {boolean} true when OK + */ + NbEventServiceBase.prototype.validateEvt = function validateEvt () { + var this$1 = this; + var evt = [], len = arguments.length; + while ( len-- ) evt[ len ] = arguments[ len ]; -/** - * validate the event name - * @param {string} evt event name - * @return {boolean} true when OK - */ -EventService.prototype.validateEvt = function validateEvt (evt) { - if (typeof evt === 'string') { + evt.forEach(function (e) { + if (typeof e !== 'string') { + this$1.logger('(validateEvt)', e); + throw new Error("event name must be string type!") + } + }); return true; - } - throw new Error("event name must be string type!") -}; + }; -/** - * Simple quick check on the two main parameters - * @param {string} evt event name - * @param {function} callback function to call - * @return {boolean} true when OK - */ -EventService.prototype.validate = function validate (evt, callback) { - if (this.validateEvt(evt)) { - if (typeof callback === 'function') { - return true; + /** + * Simple quick check on the two main parameters + * @param {string} evt event name + * @param {function} callback function to call + * @return {boolean} true when OK + */ + NbEventServiceBase.prototype.validate = function validate (evt, callback) { + if (this.validateEvt(evt)) { + if (typeof callback === 'function') { + return true; + } } - } - throw new Error("callback required to be function type!") -}; + throw new Error("callback required to be function type!") + }; -/** - * Check if this type is correct or not added in V1.5.0 - * @param {string} type for checking - * @return {boolean} true on OK - */ -EventService.prototype.validateType = function validateType (type) { - var types = ['on', 'only', 'once', 'onlyOnce']; - return !!types.filter(function (t) { return type === t; }).length; -}; + /** + * Check if this type is correct or not added in V1.5.0 + * @param {string} type for checking + * @return {boolean} true on OK + */ + NbEventServiceBase.prototype.validateType = function validateType (type) { + var types = ['on', 'only', 'once', 'onlyOnce']; + return !!types.filter(function (t) { return type === t; }).length; + }; -/** - * Run the callback - * @param {function} callback function to execute - * @param {array} payload for callback - * @param {object} ctx context or null - * @return {void} the result store in $done - */ -EventService.prototype.run = function run (callback, payload, ctx) { - this.logger('run', callback, payload, ctx); - this.$done = Reflect.apply(callback, ctx, this.toArray(payload)); -}; + /** + * Run the callback + * @param {function} callback function to execute + * @param {array} payload for callback + * @param {object} ctx context or null + * @return {void} the result store in $done + */ + NbEventServiceBase.prototype.run = function run (callback, payload, ctx) { + this.logger('(run)', callback, payload, ctx); + this.$done = Reflect.apply(callback, ctx, this.toArray(payload)); + }; -/** - * Take the content out and remove it from store id by the name - * @param {string} evt event name - * @param {string} [storeName = lazyStore] name of store - * @return {object|boolean} content or false on not found - */ -EventService.prototype.takeFromStore = function takeFromStore (evt, storeName) { + /** + * Take the content out and remove it from store id by the name + * @param {string} evt event name + * @param {string} [storeName = lazyStore] name of store + * @return {object|boolean} content or false on not found + */ + NbEventServiceBase.prototype.takeFromStore = function takeFromStore (evt, storeName) { if ( storeName === void 0 ) storeName = 'lazyStore'; - var store = this[storeName]; // it could be empty at this point - if (store) { - this.logger('takeFromStore', storeName, store); - if (store.has(evt)) { - var content = store.get(evt); - this.logger('takeFromStore', content); - store.delete(evt); - return content; + var store = this[storeName]; // it could be empty at this point + if (store) { + this.logger('(takeFromStore)', storeName, store); + if (store.has(evt)) { + var content = store.get(evt); + this.logger('(takeFromStore)', ("has " + evt), content); + store.delete(evt); + return content; + } + return false; } - return false; - } - throw new Error((storeName + " is not supported!")) -}; + throw new Error((storeName + " is not supported!")) + }; -/** - * The add to store step is similar so make it generic for resuse - * @param {object} store which store to use - * @param {string} evt event name - * @param {spread} args because the lazy store and normal store store different things - * @return {array} store and the size of the store - */ -EventService.prototype.addToStore = function addToStore (store, evt) { + /** + * The add to store step is similar so make it generic for resuse + * @param {object} store which store to use + * @param {string} evt event name + * @param {spread} args because the lazy store and normal store store different things + * @return {array} store and the size of the store + */ + NbEventServiceBase.prototype.addToStore = function addToStore (store, evt) { var args = [], len = arguments.length - 2; while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; - var fnSet; - if (store.has(evt)) { - this.logger('addToStore', (evt + " existed")); - fnSet = store.get(evt); - } else { - this.logger('addToStore', ("create new Set for " + evt)); - // this is new - fnSet = new Set(); - } - // lazy only store 2 items - this is not the case in V1.6.0 anymore - // we need to check the first parameter is string or not - if (args.length > 2) { - if (Array.isArray(args[0])) { // lazy store - // check if this type of this event already register in the lazy store - var t = args[2]; - if (!this.checkTypeInLazyStore(evt, t)) { - fnSet.add(args); - } + var fnSet; + if (store.has(evt)) { + this.logger('(addToStore)', (evt + " existed")); + fnSet = store.get(evt); } else { - if (!this.checkContentExist(args, fnSet)) { - this.logger('addToStore', "insert new", args); - fnSet.add(args); + this.logger('(addToStore)', ("create new Set for " + evt)); + // this is new + fnSet = new Set(); + } + // lazy only store 2 items - this is not the case in V1.6.0 anymore + // we need to check the first parameter is string or not + if (args.length > 2) { + if (Array.isArray(args[0])) { // lazy store + // check if this type of this event already register in the lazy store + var t = args[2]; + if (!this.checkTypeInLazyStore(evt, t)) { + fnSet.add(args); + } + } else { + if (!this.checkContentExist(args, fnSet)) { + this.logger('(addToStore)', "insert new", args); + fnSet.add(args); + } } + } else { // add straight to lazy store + fnSet.add(args); } - } else { // add straight to lazy store - fnSet.add(args); - } - store.set(evt, fnSet); - return [store, fnSet.size] -}; + store.set(evt, fnSet); + return [store, fnSet.size] + }; -/** - * @param {array} args for compare - * @param {object} fnSet A Set to search from - * @return {boolean} true on exist - */ -EventService.prototype.checkContentExist = function checkContentExist (args, fnSet) { - var list = Array.from(fnSet); - return !!list.filter(function (l) { - var hash = l[0]; - if (hash === args[0]) { + /** + * @param {array} args for compare + * @param {object} fnSet A Set to search from + * @return {boolean} true on exist + */ + NbEventServiceBase.prototype.checkContentExist = function checkContentExist (args, fnSet) { + var list = Array.from(fnSet); + return !!list.filter(function (l) { + var hash = l[0]; + if (hash === args[0]) { + return true; + } + return false; + }).length; + }; + + /** + * get the existing type to make sure no mix type add to the same store + * @param {string} evtName event name + * @param {string} type the type to check + * @return {boolean} true you can add, false then you can't add this type + */ + NbEventServiceBase.prototype.checkTypeInStore = function checkTypeInStore (evtName, type) { + this.validateEvt(evtName, type); + var all = this.$get(evtName, true); + if (all === false) { + // pristine it means you can add return true; } + // it should only have ONE type in ONE event store + return !all.filter(function (list) { + var t = list[3]; + return type !== t; + }).length; + }; + + /** + * This is checking just the lazy store because the structure is different + * therefore we need to use a new method to check it + */ + NbEventServiceBase.prototype.checkTypeInLazyStore = function checkTypeInLazyStore (evtName, type) { + this.validateEvt(evtName, type); + var store = this.lazyStore.get(evtName); + this.logger('(checkTypeInLazyStore)', store); + if (store) { + return !!Array + .from(store) + .filter(function (l) { + var t = l[2]; + return t !== type; + }).length + } return false; - }).length; -}; + }; -/** - * get the existing type to make sure no mix type add to the same store - * @param {string} evtName event name - * @param {string} type the type to check - * @return {boolean} true you can add, false then you can't add this type - */ -EventService.prototype.checkTypeInStore = function checkTypeInStore (evtName, type) { - this.validateEvt(evtName); - this.validateEvt(type); - var all = this.$get(evtName, true); - if (all === false) { - // pristine it means you can add - return true; - } - // it should only have ONE type in ONE event store - return !all.filter(function (list) { - var t = list[3]; - return type !== t; - }).length; -}; + /** + * wrapper to re-use the addToStore, + * V1.3.0 add extra check to see if this type can add to this evt + * @param {string} evt event name + * @param {string} type on or once + * @param {function} callback function + * @param {object} context the context the function execute in or null + * @return {number} size of the store + */ + NbEventServiceBase.prototype.addToNormalStore = function addToNormalStore (evt, type, callback, context) { + if ( context === void 0 ) context = null; -/** - * This is checking just the lazy store because the structure is different - * therefore we need to use a new method to check it - */ -EventService.prototype.checkTypeInLazyStore = function checkTypeInLazyStore (evtName, type) { - this.validateEvt(evtName); - this.validateEvt(type); - var store = this.lazyStore.get(evtName); - this.logger('checkTypeInLazyStore', store); - if (store) { - return !!Array - .from(store) - .filter(function (l) { - var t = l[2]; - return t !== type; - }).length - } - return false; -}; + this.logger('(addToNormalStore)', evt, type, 'try to add to normal store'); + // @TODO we need to check the existing store for the type first! + if (this.checkTypeInStore(evt, type)) { + this.logger('(addToNormalStore)', (type + " can add to " + evt + " normal store")); + var key = this.hashFnToKey(callback); + var args = [this.normalStore, evt, key, callback, context, type]; + var ref = Reflect.apply(this.addToStore, this, args); + var _store = ref[0]; + var size = ref[1]; + this.normalStore = _store; + return size; + } + return false; + }; -/** - * wrapper to re-use the addToStore, - * V1.3.0 add extra check to see if this type can add to this evt - * @param {string} evt event name - * @param {string} type on or once - * @param {function} callback function - * @param {object} context the context the function execute in or null - * @return {number} size of the store - */ -EventService.prototype.addToNormalStore = function addToNormalStore (evt, type, callback, context) { + /** + * Add to lazy store this get calls when the callback is not register yet + * so we only get a payload object or even nothing + * @param {string} evt event name + * @param {array} payload of arguments or empty if there is none + * @param {object} [context=null] the context the callback execute in + * @param {string} [type=false] register a type so no other type can add to this evt + * @return {number} size of the store + */ + NbEventServiceBase.prototype.addToLazyStore = function addToLazyStore (evt, payload, context, type) { + if ( payload === void 0 ) payload = []; if ( context === void 0 ) context = null; + if ( type === void 0 ) type = false; - this.logger('addToNormalStore', evt, type, 'add to normal store'); - // @TODO we need to check the existing store for the type first! - if (this.checkTypeInStore(evt, type)) { - this.logger((type + " can add to " + evt + " store")); - var key = this.hashFnToKey(callback); - var args = [this.normalStore, evt, key, callback, context, type]; + // this is add in V1.6.0 + // when there is type then we will need to check if this already added in lazy store + // and no other type can add to this lazy store + var args = [this.lazyStore, evt, this.toArray(payload), context]; + if (type) { + args.push(type); + } var ref = Reflect.apply(this.addToStore, this, args); - var _store = ref[0]; - var size = ref[1]; - this.normalStore = _store; + var _store = ref[0]; + var size = ref[1]; + this.lazyStore = _store; return size; + }; + + /** + * make sure we store the argument correctly + * @param {*} arg could be array + * @return {array} make sured + */ + NbEventServiceBase.prototype.toArray = function toArray (arg) { + return Array.isArray(arg) ? arg : [arg]; + }; + + /** + * setter to store the Set in private + * @param {object} obj a Set + */ + prototypeAccessors.normalStore.set = function (obj) { + NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj); + }; + + /** + * @return {object} Set object + */ + prototypeAccessors.normalStore.get = function () { + return NB_EVENT_SERVICE_PRIVATE_STORE.get(this) + }; + + /** + * setter to store the Set in lazy store + * @param {object} obj a Set + */ + prototypeAccessors.lazyStore.set = function (obj) { + NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj); + }; + + /** + * @return {object} the lazy store Set + */ + prototypeAccessors.lazyStore.get = function () { + return NB_EVENT_SERVICE_PRIVATE_LAZY.get(this) + }; + + /** + * generate a hashKey to identify the function call + * The build-in store some how could store the same values! + * @param {function} fn the converted to string function + * @return {string} hashKey + */ + NbEventServiceBase.prototype.hashFnToKey = function hashFnToKey (fn) { + return hashCode(fn.toString()) + ''; + }; + + Object.defineProperties( NbEventServiceBase.prototype, prototypeAccessors ); + + return NbEventServiceBase; +}(SuspendClass)); + +// The top level +// export +var EventService = /*@__PURE__*/(function (NbStoreService) { + function EventService(config) { + if ( config === void 0 ) config = {}; + + NbStoreService.call(this, config); } - return false; -}; -/** - * Add to lazy store this get calls when the callback is not register yet - * so we only get a payload object or even nothing - * @param {string} evt event name - * @param {array} payload of arguments or empty if there is none - * @param {object} [context=null] the context the callback execute in - * @param {string} [type=false] register a type so no other type can add to this evt - * @return {number} size of the store - */ -EventService.prototype.addToLazyStore = function addToLazyStore (evt, payload, context, type) { + if ( NbStoreService ) EventService.__proto__ = NbStoreService; + EventService.prototype = Object.create( NbStoreService && NbStoreService.prototype ); + EventService.prototype.constructor = EventService; + + var prototypeAccessors = { $done: { configurable: true } }; + + /** + * logger function for overwrite + */ + EventService.prototype.logger = function logger () {}; + + ////////////////////////// + // PUBLIC METHODS // + ////////////////////////// + + /** + * Register your evt handler, note we don't check the type here, + * we expect you to be sensible and know what you are doing. + * @param {string} evt name of event + * @param {function} callback bind method --> if it's array or not + * @param {object} [context=null] to execute this call in + * @return {number} the size of the store + */ + EventService.prototype.$on = function $on (evt , callback , context) { + var this$1 = this; + if ( context === void 0 ) context = null; + + var type = 'on'; + this.validate(evt, callback); + // first need to check if this evt is in lazy store + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register first then call later + if (lazyStoreContent === false) { + this.logger('($on)', (evt + " callback is not in lazy store")); + // @TODO we need to check if there was other listener to this + // event and are they the same type then we could solve that + // register the different type to the same event name + + return this.addToNormalStore(evt, type, callback, context) + } + this.logger('($on)', (evt + " found in lazy store")); + // this is when they call $trigger before register this callback + var size = 0; + lazyStoreContent.forEach(function (content) { + var payload = content[0]; + var ctx = content[1]; + var t = content[2]; + if (t && t !== type) { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this$1.run(callback, payload, context || ctx); + size += this$1.addToNormalStore(evt, type, callback, context || ctx); + }); + return size; + }; + + /** + * once only registered it once, there is no overwrite option here + * @NOTE change in v1.3.0 $once can add multiple listeners + * but once the event fired, it will remove this event (see $only) + * @param {string} evt name + * @param {function} callback to execute + * @param {object} [context=null] the handler execute in + * @return {boolean} result + */ + EventService.prototype.$once = function $once (evt , callback , context) { + if ( context === void 0 ) context = null; + + this.validate(evt, callback); + var type = 'once'; + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register before call $trigger + var nStore = this.normalStore; + if (lazyStoreContent === false) { + this.logger('($once)', (evt + " not in the lazy store")); + // v1.3.0 $once now allow to add multiple listeners + return this.addToNormalStore(evt, type, callback, context) + } else { + // now this is the tricky bit + // there is a potential bug here that cause by the developer + // if they call $trigger first, the lazy won't know it's a once call + // so if in the middle they register any call with the same evt name + // then this $once call will be fucked - add this to the documentation + this.logger('($once)', lazyStoreContent); + var list = Array.from(lazyStoreContent); + // should never have more than 1 + var ref = list[0]; + var payload = ref[0]; + var ctx = ref[1]; + var t = ref[2]; + if (t && t !== type) { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this.run(callback, payload, context || ctx); + // remove this evt from store + this.$off(evt); + } + }; + + /** + * This one event can only bind one callbackback + * @param {string} evt event name + * @param {function} callback event handler + * @param {object} [context=null] the context the event handler execute in + * @return {boolean} true bind for first time, false already existed + */ + EventService.prototype.$only = function $only (evt, callback, context) { + var this$1 = this; + if ( context === void 0 ) context = null; + + this.validate(evt, callback); + var type = 'only'; + var added = false; + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register before call $trigger + var nStore = this.normalStore; + if (!nStore.has(evt)) { + this.logger("($only)", (evt + " add to store")); + added = this.addToNormalStore(evt, type, callback, context); + } + if (lazyStoreContent !== false) { + // there are data store in lazy store + this.logger('($only)', (evt + " found data in lazy store to execute")); + var list = Array.from(lazyStoreContent); + // $only allow to trigger this multiple time on the single handler + list.forEach( function (l) { + var payload = l[0]; + var ctx = l[1]; + var t = l[2]; + if (t && t !== type) { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this$1.run(callback, payload, context || ctx); + }); + } + return added; + }; + + /** + * $only + $once this is because I found a very subtile bug when we pass a + * resolver, rejecter - and it never fire because that's OLD adeed in v1.4.0 + * @param {string} evt event name + * @param {function} callback to call later + * @param {object} [context=null] exeucte context + * @return {void} + */ + EventService.prototype.$onlyOnce = function $onlyOnce (evt, callback, context) { + if ( context === void 0 ) context = null; + + this.validate(evt, callback); + var type = 'onlyOnce'; + var added = false; + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register before call $trigger + var nStore = this.normalStore; + if (!nStore.has(evt)) { + this.logger("($onlyOnce)", (evt + " add to store")); + added = this.addToNormalStore(evt, type, callback, context); + } + if (lazyStoreContent !== false) { + // there are data store in lazy store + this.logger('($onlyOnce)', lazyStoreContent); + var list = Array.from(lazyStoreContent); + // should never have more than 1 + var ref = list[0]; + var payload = ref[0]; + var ctx = ref[1]; + var t = ref[2]; + if (t && t !== 'onlyOnce') { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this.run(callback, payload, context || ctx); + // remove this evt from store + this.$off(evt); + } + return added; + }; + + /** + * This is a shorthand of $off + $on added in V1.5.0 + * @param {string} evt event name + * @param {function} callback to exeucte + * @param {object} [context = null] or pass a string as type + * @param {string} [type=on] what type of method to replace + * @return {} + */ + EventService.prototype.$replace = function $replace (evt, callback, context, type) { + if ( context === void 0 ) context = null; + if ( type === void 0 ) type = 'on'; + + if (this.validateType(type)) { + this.$off(evt); + var method = this['$' + type]; + return Reflect.apply(method, this, [evt, callback, context]) + } + throw new Error((type + " is not supported!")) + }; + + /** + * trigger the event + * @param {string} evt name NOT allow array anymore! + * @param {mixed} [payload = []] pass to fn + * @param {object|string} [context = null] overwrite what stored + * @param {string} [type=false] if pass this then we need to add type to store too + * @return {number} if it has been execute how many times + */ + EventService.prototype.$trigger = function $trigger (evt , payload , context, type) { if ( payload === void 0 ) payload = []; if ( context === void 0 ) context = null; if ( type === void 0 ) type = false; - // this is add in V1.6.0 - // when there is type then we will need to check if this already added in lazy store - // and no other type can add to this lazy store - var args = [this.lazyStore, evt, this.toArray(payload), context]; - if (type) { - args.push(type); - } - var ref = Reflect.apply(this.addToStore, this, args); - var _store = ref[0]; - var size = ref[1]; - this.lazyStore = _store; - return size; -}; + this.validateEvt(evt); + var found = 0; + // first check the normal store + var nStore = this.normalStore; + this.logger('($trigger)', 'normalStore', nStore); + if (nStore.has(evt)) { + // @1.8.0 to add the suspend queue + var added = this.$queue(evt, payload, context, type); + this.logger('($trigger)', evt, 'found; add to queue: ', added); + if (added === true) { + return false; // not executed + } + var nSet = Array.from(nStore.get(evt)); + var ctn = nSet.length; + var hasOnce = false; + for (var i=0; i < ctn; ++i) { + ++found; + // this.logger('found', found) + var ref = nSet[i]; + var _ = ref[0]; + var callback = ref[1]; + var ctx = ref[2]; + var type$1 = ref[3]; + this.run(callback, payload, context || ctx); + if (type$1 === 'once' || type$1 === 'onlyOnce') { + hasOnce = true; + } + } + if (hasOnce) { + nStore.delete(evt); + } + return found; + } + // now this is not register yet + this.addToLazyStore(evt, payload, context, type); + return found; + }; -/** - * make sure we store the argument correctly - * @param {*} arg could be array - * @return {array} make sured - */ -EventService.prototype.toArray = function toArray (arg) { - return Array.isArray(arg) ? arg : [arg]; -}; + /** + * this is an alias to the $trigger + * @NOTE breaking change in V1.6.0 we swap the parameter around + * @param {string} evt event name + * @param {*} params pass to the callback + * @param {string} type of call + * @param {object} context what context callback execute in + * @return {*} from $trigger + */ + EventService.prototype.$call = function $call (evt, params, type, context) { + if ( type === void 0 ) type = false; + if ( context === void 0 ) context = null; -/** - * setter to store the Set in private - * @param {object} obj a Set - */ -prototypeAccessors.normalStore.set = function (obj) { - NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj); -}; + var args = [evt, params]; + args.push(context, type); + return Reflect.apply(this.$trigger, this, args) + }; -/** - * @return {object} Set object - */ -prototypeAccessors.normalStore.get = function () { - return NB_EVENT_SERVICE_PRIVATE_STORE.get(this) -}; + /** + * remove the evt from all the stores + * @param {string} evt name + * @return {boolean} true actually delete something + */ + EventService.prototype.$off = function $off (evt) { + this.validateEvt(evt); + var stores = [ this.lazyStore, this.normalStore ]; + var found = false; + stores.forEach(function (store) { + if (store.has(evt)) { + found = true; + store.delete(evt); + } + }); + return found; + }; -/** - * setter to store the Set in lazy store - * @param {object} obj a Set - */ -prototypeAccessors.lazyStore.set = function (obj) { - NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj); -}; + /** + * return all the listener from the event + * @param {string} evtName event name + * @param {boolean} [full=false] if true then return the entire content + * @return {array|boolean} listerner(s) or false when not found + */ + EventService.prototype.$get = function $get (evt, full) { + if ( full === void 0 ) full = false; -/** - * @return {object} the lazy store Set - */ -prototypeAccessors.lazyStore.get = function () { - return NB_EVENT_SERVICE_PRIVATE_LAZY.get(this) -}; + this.validateEvt(evt); + var store = this.normalStore; + if (store.has(evt)) { + return Array + .from(store.get(evt)) + .map( function (l) { + if (full) { + return l; + } + var key = l[0]; + var callback = l[1]; + return callback; + }) + } + return false; + }; -/** - * generate a hashKey to identify the function call - * The build-in store some how could store the same values! - * @param {function} fn the converted to string function - * @return {string} hashKey - */ -EventService.prototype.hashFnToKey = function hashFnToKey (fn) { - return hashCode(fn.toString()) + ''; -}; + /** + * store the return result from the run + * @param {*} value whatever return from callback + */ + prototypeAccessors.$done.set = function (value) { + this.logger('($done)', 'value: ', value); + if (this.keep) { + this.result.push(value); + } else { + this.result = value; + } + }; + + /** + * @TODO is there any real use with the keep prop? + * getter for $done + * @return {*} whatever last store result + */ + prototypeAccessors.$done.get = function () { + if (this.keep) { + this.logger('(get $done)', this.result); + return this.result[this.result.length - 1] + } + return this.result; + }; + + Object.defineProperties( EventService.prototype, prototypeAccessors ); -Object.defineProperties( EventService.prototype, prototypeAccessors ); + return EventService; +}(NbEventServiceBase)); // default diff --git a/packages/ws-client/src/node/socketio-clients.js b/packages/ws-client/src/node/socketio-clients.js index 7f56e6a4..fcf97a40 100644 --- a/packages/ws-client/src/node/socketio-clients.js +++ b/packages/ws-client/src/node/socketio-clients.js @@ -12,7 +12,8 @@ const { socketIoClient, socketIoClientAsync, socketIoChainConnect -} = require('./clients') +} = require('jsonql-jwt') + const { IO_ROUNDTRIP_LOGIN, IO_HANDSHAKE_LOGIN } = require('jsonql-constants') /** diff --git a/packages/ws-client/tests/connect/socketio-chain-connect-hs.test.js b/packages/ws-client/tests/jwt/socketio-chain-connect-hs.test.js similarity index 100% rename from packages/ws-client/tests/connect/socketio-chain-connect-hs.test.js rename to packages/ws-client/tests/jwt/socketio-chain-connect-hs.test.js diff --git a/packages/ws-client/tests/connect/socketio-chain-connect-rt.test.js b/packages/ws-client/tests/jwt/socketio-chain-connect-rt.test.js similarity index 100% rename from packages/ws-client/tests/connect/socketio-chain-connect-rt.test.js rename to packages/ws-client/tests/jwt/socketio-chain-connect-rt.test.js diff --git a/packages/ws-client/tests/connect/socketio-handshake.test.js b/packages/ws-client/tests/jwt/socketio-handshake.test.js similarity index 100% rename from packages/ws-client/tests/connect/socketio-handshake.test.js rename to packages/ws-client/tests/jwt/socketio-handshake.test.js diff --git a/packages/ws-client/tests/connect/socketio-roundtrip-fail.test.js b/packages/ws-client/tests/jwt/socketio-roundtrip-fail.test.js similarity index 100% rename from packages/ws-client/tests/connect/socketio-roundtrip-fail.test.js rename to packages/ws-client/tests/jwt/socketio-roundtrip-fail.test.js diff --git a/packages/ws-client/tests/connect/socketio-roundtrip.test.js b/packages/ws-client/tests/jwt/socketio-roundtrip.test.js similarity index 100% rename from packages/ws-client/tests/connect/socketio-roundtrip.test.js rename to packages/ws-client/tests/jwt/socketio-roundtrip.test.js diff --git a/packages/ws-client/tests/connect/ws-handshake.test.js b/packages/ws-client/tests/jwt/ws-handshake.test.js similarity index 100% rename from packages/ws-client/tests/connect/ws-handshake.test.js rename to packages/ws-client/tests/jwt/ws-handshake.test.js -- Gitee From 65b349f02625761f7928a60c0d67e32b212285ed Mon Sep 17 00:00:00 2001 From: Joelchu Date: Thu, 15 Aug 2019 13:50:57 +0800 Subject: [PATCH 4/9] ws-client to beta.2 --- packages/ws-client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ws-client/package.json b/packages/ws-client/package.json index 7aad0580..fd7c3373 100755 --- a/packages/ws-client/package.json +++ b/packages/ws-client/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-ws-client", - "version": "1.0.0-beta.1", + "version": "1.0.0-beta.2", "description": "This is the web socket client for jsonql-ws-server", "main": "main.js", "module": "index.js", -- Gitee From 284bf341c2cbba60250d8a184bc571da3eae85cb Mon Sep 17 00:00:00 2001 From: Joelchu Date: Thu, 15 Aug 2019 14:22:07 +0800 Subject: [PATCH 5/9] test failed but decided to break up all the different type of socket server in a server client packages --- packages/ws-client/package.json | 4 ++-- packages/ws-client/src/node/main.cjs.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/ws-client/package.json b/packages/ws-client/package.json index fd7c3373..37d20f87 100755 --- a/packages/ws-client/package.json +++ b/packages/ws-client/package.json @@ -12,7 +12,7 @@ "main.js" ], "scripts": { - "test": "npm run build:cjs && DEBUG=jsonql-ws* ava", + "test": "npm run build:cjs && DEBUG=jsonql-ws* ava --verbose", "test:browser": "DEBUG=jsonql-ws-client*,server-io-core* node ./tests/browser/run-qunit.js", "test:browser:io": "DEBUG=jsonql-ws-client*,server-io-core* NODE_ENV=io node ./tests/browser/run-qunit.js", "test:browser:ws:auth": "DEBUG=jsonql-ws-client* NODE_ENV=ws-auth node ./tests/browser/run-qunit.js", @@ -47,7 +47,6 @@ "license": "MIT", "devDependencies": { "ava": "^2.2.0", - "debug": "^4.1.1", "esm": "^3.2.25", "fs-extra": "^8.1.0", "glob": "^7.1.4", @@ -96,6 +95,7 @@ "node": ">=8" }, "dependencies": { + "debug": "^4.1.1", "jsonql-constants": "^1.7.9", "jsonql-errors": "^1.1.1", "jsonql-jwt": "^1.2.5", diff --git a/packages/ws-client/src/node/main.cjs.js b/packages/ws-client/src/node/main.cjs.js index 9903c94b..f5a8e6ae 100644 --- a/packages/ws-client/src/node/main.cjs.js +++ b/packages/ws-client/src/node/main.cjs.js @@ -7682,7 +7682,7 @@ function main(clientGenerator) { }; // use the Object.addProperty trick Object.defineProperty(wsClient, 'CLIENT_TYPE_INFO', { - value: 'version: 1.0.0-beta.1 module: cjs', + value: 'version: 1.0.0-beta.2 module: cjs', writable: false }); return wsClient; -- Gitee From ca2766aa3e56d939d47389decae984083a9bcb2b Mon Sep 17 00:00:00 2001 From: Joelchu Date: Thu, 15 Aug 2019 16:41:19 +0800 Subject: [PATCH 6/9] reorganize the packages to the sub @jsonql namespace folder --- .gitignore | 4 ++-- packages/{ => @jsonql}/event/.gitignore | 0 packages/{ => @jsonql}/event/README.md | 0 packages/{ => @jsonql}/event/dist/jsonql-event.cjs.js | 0 packages/{ => @jsonql}/event/dist/jsonql-event.d.ts | 0 packages/{ => @jsonql}/event/dist/jsonql-event.es.js | 0 packages/{ => @jsonql}/event/dist/jsonql-event.umd.js | 0 packages/{ => @jsonql}/event/index.ts | 0 packages/{ => @jsonql}/event/package.json | 0 packages/{ => @jsonql}/event/rollup.config.js | 0 packages/{ => @jsonql}/event/src/event-service.ts | 0 packages/{ => @jsonql}/event/src/hash-code.d.ts | 0 packages/{ => @jsonql}/event/src/hash-code.ts | 0 packages/{ => @jsonql}/event/src/interfaces.ts | 0 packages/{ => @jsonql}/event/src/store-service.ts | 0 packages/{ => @jsonql}/event/src/suspend.d.ts | 0 packages/{ => @jsonql}/event/src/suspend.ts | 0 packages/{ => @jsonql}/event/tests/basic.test.js | 0 packages/{ => @jsonql}/event/tests/fixtures/browser.js | 0 packages/{ => @jsonql}/event/tests/fixtures/index.html | 0 packages/{ => @jsonql}/event/tests/lazy.test.js | 0 packages/{ => @jsonql}/event/tests/map-set.test.js | 0 packages/{ => @jsonql}/event/tests/once-problem.test.js | 0 packages/{ => @jsonql}/event/tests/only-once.test.js | 0 packages/{ => @jsonql}/event/tests/only.test.js | 0 packages/{ => @jsonql}/event/tests/replace.test.js | 0 packages/{ => @jsonql}/event/tests/suspend.test.js | 0 packages/{ => @jsonql}/event/tsconfig.json | 0 28 files changed, 2 insertions(+), 2 deletions(-) rename packages/{ => @jsonql}/event/.gitignore (100%) rename packages/{ => @jsonql}/event/README.md (100%) rename packages/{ => @jsonql}/event/dist/jsonql-event.cjs.js (100%) rename packages/{ => @jsonql}/event/dist/jsonql-event.d.ts (100%) rename packages/{ => @jsonql}/event/dist/jsonql-event.es.js (100%) rename packages/{ => @jsonql}/event/dist/jsonql-event.umd.js (100%) rename packages/{ => @jsonql}/event/index.ts (100%) rename packages/{ => @jsonql}/event/package.json (100%) rename packages/{ => @jsonql}/event/rollup.config.js (100%) rename packages/{ => @jsonql}/event/src/event-service.ts (100%) rename packages/{ => @jsonql}/event/src/hash-code.d.ts (100%) rename packages/{ => @jsonql}/event/src/hash-code.ts (100%) rename packages/{ => @jsonql}/event/src/interfaces.ts (100%) rename packages/{ => @jsonql}/event/src/store-service.ts (100%) rename packages/{ => @jsonql}/event/src/suspend.d.ts (100%) rename packages/{ => @jsonql}/event/src/suspend.ts (100%) rename packages/{ => @jsonql}/event/tests/basic.test.js (100%) rename packages/{ => @jsonql}/event/tests/fixtures/browser.js (100%) rename packages/{ => @jsonql}/event/tests/fixtures/index.html (100%) rename packages/{ => @jsonql}/event/tests/lazy.test.js (100%) rename packages/{ => @jsonql}/event/tests/map-set.test.js (100%) rename packages/{ => @jsonql}/event/tests/once-problem.test.js (100%) rename packages/{ => @jsonql}/event/tests/only-once.test.js (100%) rename packages/{ => @jsonql}/event/tests/only.test.js (100%) rename packages/{ => @jsonql}/event/tests/replace.test.js (100%) rename packages/{ => @jsonql}/event/tests/suspend.test.js (100%) rename packages/{ => @jsonql}/event/tsconfig.json (100%) diff --git a/.gitignore b/.gitignore index 00f8bcca..a871408f 100755 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,8 @@ yarn.lock package-lock.json /.nyc_output -/packages/*/node_modules +/packages/**/node_modules .vscode/ -/packages/*/.nyc_output +/packages/**/.nyc_output /packages/**/tmp/* /packages/**/logs/* diff --git a/packages/event/.gitignore b/packages/@jsonql/event/.gitignore similarity index 100% rename from packages/event/.gitignore rename to packages/@jsonql/event/.gitignore diff --git a/packages/event/README.md b/packages/@jsonql/event/README.md similarity index 100% rename from packages/event/README.md rename to packages/@jsonql/event/README.md diff --git a/packages/event/dist/jsonql-event.cjs.js b/packages/@jsonql/event/dist/jsonql-event.cjs.js similarity index 100% rename from packages/event/dist/jsonql-event.cjs.js rename to packages/@jsonql/event/dist/jsonql-event.cjs.js diff --git a/packages/event/dist/jsonql-event.d.ts b/packages/@jsonql/event/dist/jsonql-event.d.ts similarity index 100% rename from packages/event/dist/jsonql-event.d.ts rename to packages/@jsonql/event/dist/jsonql-event.d.ts diff --git a/packages/event/dist/jsonql-event.es.js b/packages/@jsonql/event/dist/jsonql-event.es.js similarity index 100% rename from packages/event/dist/jsonql-event.es.js rename to packages/@jsonql/event/dist/jsonql-event.es.js diff --git a/packages/event/dist/jsonql-event.umd.js b/packages/@jsonql/event/dist/jsonql-event.umd.js similarity index 100% rename from packages/event/dist/jsonql-event.umd.js rename to packages/@jsonql/event/dist/jsonql-event.umd.js diff --git a/packages/event/index.ts b/packages/@jsonql/event/index.ts similarity index 100% rename from packages/event/index.ts rename to packages/@jsonql/event/index.ts diff --git a/packages/event/package.json b/packages/@jsonql/event/package.json similarity index 100% rename from packages/event/package.json rename to packages/@jsonql/event/package.json diff --git a/packages/event/rollup.config.js b/packages/@jsonql/event/rollup.config.js similarity index 100% rename from packages/event/rollup.config.js rename to packages/@jsonql/event/rollup.config.js diff --git a/packages/event/src/event-service.ts b/packages/@jsonql/event/src/event-service.ts similarity index 100% rename from packages/event/src/event-service.ts rename to packages/@jsonql/event/src/event-service.ts diff --git a/packages/event/src/hash-code.d.ts b/packages/@jsonql/event/src/hash-code.d.ts similarity index 100% rename from packages/event/src/hash-code.d.ts rename to packages/@jsonql/event/src/hash-code.d.ts diff --git a/packages/event/src/hash-code.ts b/packages/@jsonql/event/src/hash-code.ts similarity index 100% rename from packages/event/src/hash-code.ts rename to packages/@jsonql/event/src/hash-code.ts diff --git a/packages/event/src/interfaces.ts b/packages/@jsonql/event/src/interfaces.ts similarity index 100% rename from packages/event/src/interfaces.ts rename to packages/@jsonql/event/src/interfaces.ts diff --git a/packages/event/src/store-service.ts b/packages/@jsonql/event/src/store-service.ts similarity index 100% rename from packages/event/src/store-service.ts rename to packages/@jsonql/event/src/store-service.ts diff --git a/packages/event/src/suspend.d.ts b/packages/@jsonql/event/src/suspend.d.ts similarity index 100% rename from packages/event/src/suspend.d.ts rename to packages/@jsonql/event/src/suspend.d.ts diff --git a/packages/event/src/suspend.ts b/packages/@jsonql/event/src/suspend.ts similarity index 100% rename from packages/event/src/suspend.ts rename to packages/@jsonql/event/src/suspend.ts diff --git a/packages/event/tests/basic.test.js b/packages/@jsonql/event/tests/basic.test.js similarity index 100% rename from packages/event/tests/basic.test.js rename to packages/@jsonql/event/tests/basic.test.js diff --git a/packages/event/tests/fixtures/browser.js b/packages/@jsonql/event/tests/fixtures/browser.js similarity index 100% rename from packages/event/tests/fixtures/browser.js rename to packages/@jsonql/event/tests/fixtures/browser.js diff --git a/packages/event/tests/fixtures/index.html b/packages/@jsonql/event/tests/fixtures/index.html similarity index 100% rename from packages/event/tests/fixtures/index.html rename to packages/@jsonql/event/tests/fixtures/index.html diff --git a/packages/event/tests/lazy.test.js b/packages/@jsonql/event/tests/lazy.test.js similarity index 100% rename from packages/event/tests/lazy.test.js rename to packages/@jsonql/event/tests/lazy.test.js diff --git a/packages/event/tests/map-set.test.js b/packages/@jsonql/event/tests/map-set.test.js similarity index 100% rename from packages/event/tests/map-set.test.js rename to packages/@jsonql/event/tests/map-set.test.js diff --git a/packages/event/tests/once-problem.test.js b/packages/@jsonql/event/tests/once-problem.test.js similarity index 100% rename from packages/event/tests/once-problem.test.js rename to packages/@jsonql/event/tests/once-problem.test.js diff --git a/packages/event/tests/only-once.test.js b/packages/@jsonql/event/tests/only-once.test.js similarity index 100% rename from packages/event/tests/only-once.test.js rename to packages/@jsonql/event/tests/only-once.test.js diff --git a/packages/event/tests/only.test.js b/packages/@jsonql/event/tests/only.test.js similarity index 100% rename from packages/event/tests/only.test.js rename to packages/@jsonql/event/tests/only.test.js diff --git a/packages/event/tests/replace.test.js b/packages/@jsonql/event/tests/replace.test.js similarity index 100% rename from packages/event/tests/replace.test.js rename to packages/@jsonql/event/tests/replace.test.js diff --git a/packages/event/tests/suspend.test.js b/packages/@jsonql/event/tests/suspend.test.js similarity index 100% rename from packages/event/tests/suspend.test.js rename to packages/@jsonql/event/tests/suspend.test.js diff --git a/packages/event/tsconfig.json b/packages/@jsonql/event/tsconfig.json similarity index 100% rename from packages/event/tsconfig.json rename to packages/@jsonql/event/tsconfig.json -- Gitee From 8c116dd3c5b9bc40f90a3e7a67ad2a1a4fb24129 Mon Sep 17 00:00:00 2001 From: Joelchu Date: Thu, 15 Aug 2019 16:55:56 +0800 Subject: [PATCH 7/9] init all the new packages --- packages/@jsonql/event/package.json | 8 ++++---- packages/@jsonql/primus/package.json | 20 ++++++++++++++++++++ packages/@jsonql/socketio/package.json | 18 ++++++++++++++++++ packages/@jsonql/ws/package.json | 20 ++++++++++++++++++++ 4 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 packages/@jsonql/primus/package.json create mode 100644 packages/@jsonql/socketio/package.json create mode 100644 packages/@jsonql/ws/package.json diff --git a/packages/@jsonql/event/package.json b/packages/@jsonql/event/package.json index 2fbeb465..24bc4ee7 100644 --- a/packages/@jsonql/event/package.json +++ b/packages/@jsonql/event/package.json @@ -1,7 +1,7 @@ { "name": "@jsonql/event", - "version": "1.2.1", - "description": "Ported from nb-event-service rewritten with Typescript", + "version": "1.2.2", + "description": "Event handler library ported from nb-event-service rewritten with Typescript", "main": "dist/jsonql-event.cjs.js", "browser": "dist/jsonql-event.umd.js", "module": "dist/jsonql-event.es.js", @@ -38,9 +38,9 @@ "devDependencies": { "ava": "^2.2.0", "debug": "^4.1.1", - "rollup": "^1.17.0", + "rollup": "^1.19.4", "rollup-plugin-typescript2": "^0.22.1", - "server-io-core": "^1.2.0-beta.2", + "server-io-core": "^1.2.0", "ts-node": "^8.3.0", "typescript": "^3.5.3" }, diff --git a/packages/@jsonql/primus/package.json b/packages/@jsonql/primus/package.json new file mode 100644 index 00000000..a287607f --- /dev/null +++ b/packages/@jsonql/primus/package.json @@ -0,0 +1,20 @@ +{ + "name": "@jsonql/primus", + "version": "0.0.1", + "description": "jsonql primus client / server package", + "main": "index.js", + "scripts": { + "test": "ava" + }, + "keywords": [ + "jsonql", + "primus", + "socket", + "client", + "socket", + "server", + "node" + ], + "author": "Joel Chu ", + "license": "ISC" +} diff --git a/packages/@jsonql/socketio/package.json b/packages/@jsonql/socketio/package.json new file mode 100644 index 00000000..033d269f --- /dev/null +++ b/packages/@jsonql/socketio/package.json @@ -0,0 +1,18 @@ +{ + "name": "@jsonql/socketio", + "version": "0.0.1", + "description": "Socket.io client / server module for jsonql", + "main": "index.js", + "scripts": { + "test": "ava" + }, + "keywords": [ + "jsonql", + "socket.io", + "client", + "server", + "node" + ], + "author": "Joel Chu ", + "license": "ISC" +} diff --git a/packages/@jsonql/ws/package.json b/packages/@jsonql/ws/package.json new file mode 100644 index 00000000..05aff1f4 --- /dev/null +++ b/packages/@jsonql/ws/package.json @@ -0,0 +1,20 @@ +{ + "name": "@jsonql/ws", + "version": "0.0.1", + "description": "WS (WebSocket) client / server module for jsonql", + "main": "index.js", + "scripts": { + "test": "ava" + }, + "keywords": [ + "jsonql", + "ws", + "WebSocket", + "socket", + "client", + "server", + "node" + ], + "author": "Joel Chu ", + "license": "ISC" +} -- Gitee From 8fb3bfd811a1723ea99b3d3647a8c2add981c217 Mon Sep 17 00:00:00 2001 From: Joelchu Date: Thu, 15 Aug 2019 17:19:03 +0800 Subject: [PATCH 8/9] move the other related packages into their respective folder --- packages/{ => @jsonql}/cli/package.json | 0 packages/{ => @jsonql}/client/package.json | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename packages/{ => @jsonql}/cli/package.json (100%) rename packages/{ => @jsonql}/client/package.json (100%) diff --git a/packages/cli/package.json b/packages/@jsonql/cli/package.json similarity index 100% rename from packages/cli/package.json rename to packages/@jsonql/cli/package.json diff --git a/packages/client/package.json b/packages/@jsonql/client/package.json similarity index 100% rename from packages/client/package.json rename to packages/@jsonql/client/package.json -- Gitee From a07d8bebd97a758e1fdc3e666180aaee3a0acb1b Mon Sep 17 00:00:00 2001 From: Joelchu Date: Thu, 15 Aug 2019 17:23:17 +0800 Subject: [PATCH 9/9] update deps and verify working --- packages/@jsonql/client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@jsonql/client/package.json b/packages/@jsonql/client/package.json index 6a8a238e..1fcf1cd6 100644 --- a/packages/@jsonql/client/package.json +++ b/packages/@jsonql/client/package.json @@ -1,6 +1,6 @@ { "name": "@jsonql/client", - "version": "1.0.0-alpha.1", + "version": "0.0.1", "description": "jsonql combine client for http / ws develop with Typescript", "main": "index.js", "module": "src/index.ts", -- Gitee