diff --git a/packages/@jsonql/security/main.js b/packages/@jsonql/security/main.js
index 1e2300a0c38f2057eb6b282a735504cd79e87c11..9089f86d6dd8ca5537ef1a42c2ea82823dc87eaf 100644
--- a/packages/@jsonql/security/main.js
+++ b/packages/@jsonql/security/main.js
@@ -17,6 +17,8 @@ const {
} = require('./src/server')
const {
+ getCache,
+ isCacheObj,
isNodeCache,
getNodeCache,
getToken,
@@ -44,6 +46,8 @@ module.exports = {
decryptWithPrivatePem,
// new csrf and node cache related stuff
+ getCache,
+ isCacheObj,
isNodeCache,
getNodeCache,
getToken,
diff --git a/packages/@jsonql/security/module.js b/packages/@jsonql/security/module.js
index d9caa27421fd4d6fdf3774ad2486ee94b752c1c4..bb12f948472bd21af7e4553dea228a24a6a75869 100644
--- a/packages/@jsonql/security/module.js
+++ b/packages/@jsonql/security/module.js
@@ -4,6 +4,12 @@ import {
decodeToken,
tokenValidator
} from './src/client'
+/* // do we need this on the client side?
+import {
+ isCacheObj,
+ getCache
+} from './src/cache'
+*/
export {
decodeToken,
diff --git a/packages/@jsonql/security/package.json b/packages/@jsonql/security/package.json
index 3343adb37d70f499526f15055fc01c44f312ec1a..d9461955fe48d7c7488ccd5b139686bd5b7e6bba 100644
--- a/packages/@jsonql/security/package.json
+++ b/packages/@jsonql/security/package.json
@@ -1,6 +1,6 @@
{
"name": "@jsonql/security",
- "version": "0.9.1",
+ "version": "0.9.4",
"description": "jwt authentication helpers library for jsonql browser / node",
"main": "main.js",
"module": "index.js",
@@ -16,6 +16,7 @@
"test:rsa-pem": "DEBUG=jsonql-jwt* ava ./tests/rsa-pem-keys.test.js",
"test:rsa": "DEBUG=jsonql-jwt* ava ./tests/rsa-keys.test.js",
"test:decode": "DEBUG=jsonql-jwt* ava ./tests/jwt-decode.test.js",
+ "test:cache": "DEBUG=jsonql-security* ava ./tests/cache.test.js",
"prepare": "NODE_ENV=production npm run build"
},
"files": [
@@ -39,14 +40,13 @@
"dependencies": {
"colors": "^1.4.0",
"fs-extra": "^9.0.0",
- "jsonql-constants": "^2.0.11",
+ "jsonql-constants": "^2.0.14",
"jsonql-errors": "^1.2.1",
"jsonql-params-validator": "^1.6.2",
- "jsonql-utils": "^1.2.5",
+ "jsonql-utils": "^1.2.6",
"jsonwebtoken": "^8.5.1",
"jwt-decode": "^2.2.0",
- "nanoid": "^2.1.11",
- "node-cache": "^5.1.0",
+ "nanoid": "^3.0.0",
"socketio-jwt": "^4.5.0",
"yargs": "^15.3.1"
},
@@ -60,7 +60,7 @@
"debug": "^4.1.1",
"esm": "^3.2.25",
"koa": "^2.11.0",
- "rollup": "^2.1.0",
+ "rollup": "^2.2.0",
"rollup-plugin-alias": "^2.2.0",
"rollup-plugin-async": "^1.2.0",
"rollup-plugin-buble": "^0.19.8",
diff --git a/packages/@jsonql/security/src/cache/csrf-methods.js b/packages/@jsonql/security/src/cache/csrf-methods.js
index ae3d1eaf27c8e1a1ac1b85f0d5cb89115cff92e4..b6ad076a698574d3922d90d9665c77c53a520ad0 100644
--- a/packages/@jsonql/security/src/cache/csrf-methods.js
+++ b/packages/@jsonql/security/src/cache/csrf-methods.js
@@ -1,19 +1,22 @@
-const nanoid = require('nanoid')
+const { nanoid } = require('nanoid')
const { JsonqlError } = require('jsonql-errors')
// const { getNodeCache } = require('./get-node-cache')
// call this first
// const store = getNodeCache()
const STORE_FAIL_ERR = 'unable to store the token in node cache!'
-
+const { getCache, isCacheObj } = require('./get-cache')
/**
* Generate a token and check if it's in the store
* @param {object} store explicitly pass the store instead of using the global one
* @return {string} token
*/
function getToken(store) {
+ // therefore we don't need to pass the init cache object here
+ store = isCacheObj(store) ? store : getCache() // this could create a confusion unsync different store
let token = nanoid()
+
// test if the token exist
- if (store.has(token)) {
+ if (store.$has(token)) {
// call itself again until find a key not in store
return getToken(store)
}
@@ -28,7 +31,7 @@ function getToken(store) {
function createCSRFToken(store) {
let token = getToken(store)
// not setting the TTL at the moment, but we should in the future
- if (store.set(token, Date.now())) {
+ if (store.$set(token, Date.now())) {
return token
}
throw new JsonqlError('createCSRFToken', STORE_FAIL_ERR)
@@ -41,7 +44,7 @@ function createCSRFToken(store) {
* @return {boolean}
*/
function isCSRFTokenExist(store, token) {
- return store.has(token)
+ return store.$has(token)
}
diff --git a/packages/@jsonql/security/src/cache/diy-cache.js b/packages/@jsonql/security/src/cache/diy-cache.js
new file mode 100644
index 0000000000000000000000000000000000000000..0d37b3ec8b5b799155bf5689414bde45b2a2fd10
--- /dev/null
+++ b/packages/@jsonql/security/src/cache/diy-cache.js
@@ -0,0 +1,63 @@
+// just fucking around with the cache object
+// NodeCache is a piece of shit
+
+
+class DiyCache {
+
+ constructor(opts = {}) {
+ const { log } = opts
+ if (typeof log === 'function') {
+ this.$log = log
+ }
+
+ this.$store = new Map()
+ }
+
+ // placeeholder
+ $log() {
+
+ }
+
+ // alias
+ $has(key) {
+ return this.$store.has(key) || false
+ }
+
+ // note this actually return the value itself
+ $set(key, value) {
+ this.$store.set(key, value)
+ return this.$has(key)
+ }
+
+ // get it and make sure it return boolen false when nothing
+ $get(key) {
+ return this.$store.get(key) || false
+ }
+
+ // alias to delete
+ $remove(key) {
+ return this.$store.delete(key)
+ }
+
+ // return the key value then remove it
+ $take(key) {
+ if (this.has(key)) {
+ const value = this.$store.get(key)
+ this.remove(key)
+ return value
+ }
+ return false
+ }
+
+ // alias to entries return interable object
+ $all() {
+ return this.$store.entries()
+ }
+
+ $size() {
+ return this.$store.size
+ }
+
+}
+
+module.exports = { DiyCache }
diff --git a/packages/@jsonql/security/src/cache/get-node-cache.js b/packages/@jsonql/security/src/cache/get-cache.js
similarity index 83%
rename from packages/@jsonql/security/src/cache/get-node-cache.js
rename to packages/@jsonql/security/src/cache/get-cache.js
index 8072c4a02441cd2c736342c7a22852a7d95b651b..d83cd43020d57d243ff319491cb0d24d4f496e8f 100644
--- a/packages/@jsonql/security/src/cache/get-node-cache.js
+++ b/packages/@jsonql/security/src/cache/get-cache.js
@@ -20,23 +20,29 @@ maxKeys: (default: -1) specifies a maximum amount of keys that can be stored in
// in this structure {CSRF-TOKEN: TIMESTAMP}
// so you can check if this key actually exist or not
// const debug = require('debug')('jsonql-ws-server-core:share:get-node-cache')
-const NodeCache = require('node-cache')
+// const NodeCache = require('node-cache')
// need to rethink should we do it like this
// global.jsonqlLocalNodeCacheStore = {}
-
+const { DiyCache } = require('./diy-cache')
/**
- * We don't want to init the node cache everytime
- * so we put that in a global value
+ * We dont' use the global property like before anymore
+ * Because that could be a security risk
* @param {objec} opts configuration
* @return {object} the nodeCache instance
*/
-function getNodeCache(opts = {}) {
- return new NodeCache(opts)
-}
-
-function isNodeCache(store) {
- return store instanceof NodeCache
-}
+function getCache(opts = {}) {
+ return new DiyCache(opts)
+}
+/**
+ * check if the store is DiyCache
+ * @param {*} store
+ */
+function isCacheObj(store) {
+ return store instanceof DiyCache
+}
-module.exports = { getNodeCache, isNodeCache }
\ No newline at end of file
+module.exports = {
+ getCache,
+ isCacheObj
+}
\ No newline at end of file
diff --git a/packages/@jsonql/security/src/cache/index.js b/packages/@jsonql/security/src/cache/index.js
index 08cddae5d385fd878d4a2c4b7a7972c5498f04ff..cd6df5180173b3062b00ad2d02e0e06a42d3ca7d 100644
--- a/packages/@jsonql/security/src/cache/index.js
+++ b/packages/@jsonql/security/src/cache/index.js
@@ -1,11 +1,10 @@
// new node side cache module using node-cache and re-use everywhere
-const { getNodeCache,isNodeCache } = require('./get-node-cache')
+const { getCache, isCacheObj } = require('./get-cache')
const { getToken, createCSRFToken, isCSRFTokenExist } = require('./csrf-methods')
-
module.exports = {
- isNodeCache,
- getNodeCache,
+ getCache,
+ isCacheObj,
getToken,
createCSRFToken,
isCSRFTokenExist
diff --git a/packages/@jsonql/security/tests/cache.test.js b/packages/@jsonql/security/tests/cache.test.js
index ea8aaf07538b6a3ae86f534a4843e03437d83ead..b83dc757857950079a7d6944228e9241f773dcaf 100644
--- a/packages/@jsonql/security/tests/cache.test.js
+++ b/packages/@jsonql/security/tests/cache.test.js
@@ -1,33 +1,56 @@
// testing the cache with the associate methods
const test = require('ava')
const {
- getNodeCache,
- isNodeCache,
+ getCache,
+ isCacheObj,
createCSRFToken,
isCSRFTokenExist
} = require('../src/cache')
+const debug = require('debug')('jsonql-security:cache')
+
test.before(t => {
- t.context.store = getNodeCache()
+ t.context.store = getCache()
})
-test(`Test the basic node-cache wrapper methods`, t => {
- const check = isNodeCache(t.context.store)
+test(`Test the CSRF token get and store`, t => {
+ // test it without the cache object
+ const token = createCSRFToken(t.context.store)
- t.true(check)
+ t.truthy(token, 'Should able to generate token')
+
+ const existed = isCSRFTokenExist(t.context.store, token)
+
+ t.true(existed, 'The token should existed')
})
+test(`Test our own DiyCache`, t => {
+ const store = getCache()
-test(`Test the CSRF token get and store`, t => {
+ const check = isCacheObj(store)
- const token = createCSRFToken(t.context.store)
+ t.true(check)
- t.truthy(token, 'Should able to generate token')
+ const key = 'some-fn'
+ function callme(msg) {
+ return `Hello yes, I got your: ${msg}`
+ }
- const existed = isCSRFTokenExist(t.context.store, token)
+ const result1 = store.$set(key, callme)
+ debug('take a look at what return', result1)
- t.true(existed, 'The token should existed')
+ const fn1 = store.$get(key)
+ const msg1 = fn1('moron')
+
+ t.truthy(msg1.indexOf('moron'))
+
+ t.true(typeof fn1 === 'function')
+
+ const fn2 = store.$get(key)
+ const msg2 = fn2('indiot!')
+
+ t.truthy(msg2.indexOf('indiot'))
})
diff --git a/packages/@jsonql/store/README.md b/packages/@jsonql/store/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ccc99b6510354b69fc3f721e8dd907445252e88b
--- /dev/null
+++ b/packages/@jsonql/store/README.md
@@ -0,0 +1,84 @@
+# @jsonql/store
+
+This is a VERY simple in-memory store with a event hook.
+
+What that mean is, whenever you call this store, you can hook into it by listen to the event,
+and do your thing; such as return value from the store of your own choice, save value to your store etc.
+
+The event hook is using [@to1source/event](https://npmjs.com/package/@to1source/event)
+
+## Example
+
+```js
+const {
+ JsonqlStore,
+ SET_EVT
+} from '@jsonql/store'
+
+const cache = new JsonqlStore()
+
+cache.set('key', 'some value')
+
+// listen to the event
+
+cache.$on(SET_EVT, function(value) {
+ // here you will get the value just set
+ // which is 'some value'
+})
+```
+
+## API
+
+This module export the follow:
+
+- JsonqlStore
+- HAS_EVT
+- SET_EVT
+- GET_EVT
+- DELETE_EVT
+- TAKE_EVT
+- ALL_EVT
+- SIZE_EVT
+- CLEAR_EVT
+- AVAILABLE_EVTS
+
+### JsonqlStore
+
+The main class interface
+
+```js
+
+const store = new JsonqlStore()
+
+// or if you want to take a look inside
+// example using debug
+
+const logger = require('debug')('your-key')
+
+const store = new JsonqlStore({ logger })
+
+```
+
+### store.has HAS_EVT
+
+### store.set SET_EVT
+
+### store.get GET_EVT
+
+### store.delete DELETE_EVT
+
+### store.take TAKE_EVT
+
+### store.all ALL_EVT
+
+### store.size SIZE_EVT (alias JsonqlStore.length)
+
+### store.clear CLEAR_EVT
+
+---
+
+Joel Chu (c) 2020
+
+[NEWBRAN LTD](https://newbran.ch)
+
+[TO1SOURCE](https://to1source.com)
\ No newline at end of file
diff --git a/packages/@jsonql/store/dist/jsonql-store.cjs.js b/packages/@jsonql/store/dist/jsonql-store.cjs.js
new file mode 100644
index 0000000000000000000000000000000000000000..93e6dc5d1426b16a5aa30f7e568d4ae682d07343
--- /dev/null
+++ b/packages/@jsonql/store/dist/jsonql-store.cjs.js
@@ -0,0 +1,2 @@
+"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t="You are trying to register an event already been taken by other type:",e=["on","only","once","onlyOnce"],r=["on","only"];function o(t){return t instanceof RegExp}function n(t){return"string"==typeof t}function i(t){if(n(t))throw new Error("Wrong type, we want number!");return!isNaN(parseInt(t))}var s=new WeakMap,a=new WeakMap,u=function(){},l={$name:{configurable:!0},is:{configurable:!0}};u.prototype.logger=function(){},l.$name.get=function(){return"to1source-event"},l.is.get=function(){return this.$name},u.prototype.validateEvt=function(){for(var t=this,e=[],r=arguments.length;r--;)e[r]=arguments[r];return e.forEach((function(e){if(!n(e))throw t.logger("(validateEvt)",e),new Error("Event name must be string type! we got "+typeof e)})),!0},u.prototype.validate=function(t,e){if(this.validateEvt(t)&&"function"==typeof e)return!0;throw new Error("callback required to be function type! we got "+typeof e)},u.prototype.validateType=function(t){return this.validateEvt(t),!!e.filter((function(e){return t===e})).length},u.prototype.run=function(t,e,r){return this.logger("(run) callback:",t,"payload:",e,"context:",r),this.$done=Reflect.apply(t,r,this.toArray(e)),this.$done},u.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,e){return(t=(t<<5)-t+e.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(u.prototype,l);var h=["has","set","get","delete","take","all","size","clear"],p=function(t){function e(e){void 0===e&&(e={}),t.call(this,e),this.$store=new Map}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={length:{configurable:!0}};return e.prototype.has=function(t){var e=this.$store.has(t)||!1;return this.$trigger("has",[t,e]),e},e.prototype.set=function(t,e){return this.$store.set(t,e),this.$trigger("set",[t,e]),this.has(t)},e.prototype.get=function(t){var e=this.$store.get(t)||!1;return this.$trigger("get",[t,e]),e},e.prototype.delete=function(t){var e=this.$store.delete(t);return this.$trigger("delete",[t,e]),e},e.prototype.take=function(t){if(this.has(t)){var e=this.$store.get(t);return this.$trigger("take",[t,e]),this.$store.delete(t),e}return this.$trigger("take",[t]),!1},e.prototype.all=function(t){void 0===t&&(t=!1);var e=this.$store.entries(),r=t?Array.from(e):e;return this.$trigger("all",[r]),r},e.prototype.size=function(){var t=this.$store.size;return this.$trigger("size",[t]),t},r.length.get=function(){return this.size()},e.prototype.clear=function(){this.$store.clear(),this.$trigger("clear")},e.prototype.on=function(t,e,r){if(void 0===r&&(r=null),!!h.filter((function(e){return e===t})).length)return this.$on(t,e,r);throw new Error(t+" is not one of ours!")},Object.defineProperties(e.prototype,r),e}(function(e){function r(t){void 0===t&&(t={}),e.call(this,t)}e&&(r.__proto__=e),r.prototype=Object.create(e&&e.prototype),r.prototype.constructor=r;var o={$done:{configurable:!0}};return r.prototype.$on=function(e,r,o){var n=this;void 0===o&&(o=null);this.validate(e,r);var i=this.takeFromStore(e);if(!1===i)return this.logger('($on) "'+e+'" is not in lazy store'),this.addToNormalStore(e,"on",r,o);this.logger("($on) "+e+" found in lazy store");var s=0;return i.forEach((function(i){var a=i[0],u=i[1],l=i[2];if(l&&"on"!==l)throw new Error(t+" "+l);n.logger("($on)",'call run "'+e+'"'),n.run(r,a,o||u),s+=n.addToNormalStore(e,"on",r,o||u)})),this.logger("($on) return size "+s),s},r.prototype.$once=function(e,r,o){void 0===o&&(o=null),this.validate(e,r);var n=this.takeFromStore(e);if(!1===n)return this.logger('($once) "'+e+'" is not in the lazy store'),this.addToNormalStore(e,"once",r,o);this.logger("($once)",n);var i=Array.from(n)[0],s=i[0],a=i[1],u=i[2];if(u&&"once"!==u)throw new Error(t+" "+u);this.logger("($once)",'call run "'+e+'"'),this.run(r,s,o||a),this.$off(e)},r.prototype.$only=function(e,r,o){var n=this;void 0===o&&(o=null),this.validate(e,r);var i=!1,s=this.takeFromStore(e);(this.normalStore.has(e)||(this.logger('($only) "'+e+'" add to normalStore'),i=this.addToNormalStore(e,"only",r,o)),!1!==s)&&(this.logger('($only) "'+e+'" found data in lazy store to execute'),Array.from(s).forEach((function(i){var s=i[0],a=i[1],u=i[2];if(u&&"only"!==u)throw new Error(t+" "+u);n.logger('($only) call run "'+e+'"'),n.run(r,s,o||a)})));return i},r.prototype.$onlyOnce=function(e,r,o){void 0===o&&(o=null),this.validate(e,r);var n=!1,i=this.takeFromStore(e);if(this.normalStore.has(e)||(this.logger('($onlyOnce) "'+e+'" add to normalStore'),n=this.addToNormalStore(e,"onlyOnce",r,o)),!1!==i){this.logger("($onlyOnce)",i);var s=Array.from(i)[0],a=s[0],u=s[1],l=s[2];if(l&&"onlyOnce"!==l)throw new Error(t+" "+l);this.logger('($onlyOnce) call run "'+e+'"'),this.run(r,a,o||u),this.$off(e)}return n},r.prototype.$max=function(t,e,r){if(void 0===r&&(r=null),this.validateEvt(t),i(e)&&e>0){if(!1!==this.$get(t,!0)){var o=this.searchMapEvt(t);if(o.length){var n=o[0][3],s=(this.checkMaxStore(t,e),this);return function(){for(var e=[],o=arguments.length;o--;)e[o]=arguments[o];var i=s.getMaxStore(t),a=-1;if(i>0){var u=s.$call(t,n,r);if(Reflect.apply(u,s,e),-1===(a=s.checkMaxStore(t)))return s.$off(t),-1}return a}}}return this.logger("The "+t+" is not registered, can not execute non-existing event at the moment"),-1}throw new Error("Expect max to be an integer and greater than zero! But we got ["+typeof e+"]"+e+" instead")},r.prototype.$replace=function(t,e,r,o){if(void 0===r&&(r=null),void 0===o&&(o="on"),this.validateType(o)){this.$off(t);var n=this["$"+o];return this.logger("($replace)",t,e),Reflect.apply(n,this,[t,e,r])}throw new Error(o+" is not supported!")},r.prototype.$trigger=function(t,e,r,o){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===o&&(o=!1),this.validateEvt(t);var n=0,i=this.normalStore;if(this.logger("($trigger) normalStore",i),i.has(t)){if(this.logger('($trigger) "'+t+'" found'),this.$queue(t,e,r,o))return this.logger('($trigger) Currently suspended "'+t+'" added to queue, nothing executed. Exit now.'),!1;for(var s=Array.from(i.get(t)),a=s.length,u=!1,l=0;l0&&--r,!(r>0))return this.maxCountStore.delete(t),this.logger("remove "+t+" from maxStore"),-1;this.maxCountStore.set(t,r)}return r}throw new Error("Expect max to be an integer, but we got "+typeof e+" "+e)},e.prototype.searchMapEvt=function(t){var e=this.$get(t,!0).filter((function(t){var e,o=t[3];return e=o,!!r.filter((function(t){return e===t})).length}));return e.length?e:[]},e.prototype.takeFromStore=function(t,e){void 0===e&&(e="lazyStore");var r=this[e];if(r){if(this.logger("(takeFromStore)",e,r),r.has(t)){var o=r.get(t);return this.logger('(takeFromStore) has "'+t+'"',o),r.delete(t),o}return!1}throw new Error('"'+e+'" is not supported!')},e.prototype.findFromStore=function(t,e,r){return void 0===r&&(r=!1),!!e.has(t)&&Array.from(e.get(t)).map((function(t){return r?t:t[1]}))},e.prototype.removeFromStore=function(t,e){return!!e.has(t)&&(this.logger("($off)",t),e.delete(t),!0)},e.prototype.getStoreSet=function(t,e){var r;return t.has(e)?(this.logger('(addToStore) "'+e+'" existed'),r=t.get(e)):(this.logger('(addToStore) create new Set for "'+e+'"'),r=new Set),r},e.prototype.addToStore=function(t,e){for(var r=[],o=arguments.length-2;o-- >0;)r[o]=arguments[o+2];var n=this.getStoreSet(t,e);if(r.length>2)if(Array.isArray(r[0])){var i=r[2];this.checkTypeInLazyStore(e,i)||n.add(r)}else this.checkContentExist(r,n)||(this.logger("(addToStore) insert new",r),n.add(r));else n.add(r);return t.set(e,n),[t,n.size]},e.prototype.checkContentExist=function(t,e){return!!Array.from(e).filter((function(e){return e[0]===t[0]})).length},e.prototype.checkTypeInStore=function(t,e){this.validateEvt(t,e);var r=this.$get(t,!0);return!1===r||!r.filter((function(t){var r=t[3];return e!==r})).length},e.prototype.checkTypeInLazyStore=function(t,e){this.validateEvt(t,e);var r=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",r),!!r&&!!Array.from(r).filter((function(t){return t[2]!==e})).length},e.prototype.addToNormalStore=function(t,e,r,o){if(void 0===o&&(o=null),this.logger('(addToNormalStore) try to add "'+e+'" --\x3e "'+t+'" to normal store'),this.checkTypeInStore(t,e)){this.logger("(addToNormalStore)",'"'+e+'" --\x3e "'+t+'" can add to normal store');var n=this.hashFnToKey(r),i=[this.normalStore,t,n,r,o,e],s=Reflect.apply(this.addToStore,this,i),a=s[0],u=s[1];return this.normalStore=a,u}return!1},e.prototype.addToLazyStore=function(t,e,r,o){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===o&&(o=!1);var n=[this.lazyStore,t,this.toArray(e),r];o&&n.push(o);var i=Reflect.apply(this.addToStore,this,n),s=i[0],a=i[1];return this.lazyStore=s,this.logger("(addToLazyStore) size: "+a),a},e.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},o.normalStore.set=function(t){s.set(this,t)},o.normalStore.get=function(){return s.get(this)},o.lazyStore.set=function(t){a.set(this,t)},o.lazyStore.get=function(){return a.get(this)},Object.defineProperties(e.prototype,o),e}(function(t){function e(){t.call(this),this.__suspend_state__=null,this.__pattern__=null,this.queueStore=new Set}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={$queues:{configurable:!0}};return e.prototype.$suspend=function(){this.logger("---\x3e SUSPEND ALL OPS <---"),this.__suspend__(!0)},e.prototype.$release=function(){this.logger("---\x3e RELEASE SUSPENDED QUEUE <---"),this.__suspend__(!1)},e.prototype.$suspendEvent=function(t){var e=function(t){switch(!0){case!0===o(t):return t;case!0===n(t):return new RegExp(t);default:return!1}}(t);if(o(e))return this.__pattern__=e,this.$suspend();throw new Error('We expect a pattern variable to be string or RegExp, but we got "'+typeof e+'" instead')},e.prototype.$queue=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];if(this.logger("($queue) get called"),!0===this.__suspend_state__){if(o(this.__pattern__)){var n=this.__pattern__.test(t);if(!n)return!1}this.logger("($queue) added to $queue",e),this.queueStore.add([t].concat(e))}return!!this.__suspend_state__},r.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},e.prototype.__suspend__=function(t){if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value! we got "+typeof t);var e=this.__suspend_state__;this.__suspend_state__=t,this.logger('($suspend) Change from "'+e+'" --\x3e "'+t+'"'),!0===e&&!1===t&&this.__release__()},e.prototype.__release__=function(){var t=this,e=this.queueStore.size,r=this.__pattern__;if(this.__pattern__=null,this.logger("(release) was called with "+e+(r?' for "'+r+'"':"")+" item"+(e>1?"s":"")),e>0){var o=Array.from(this.queueStore);this.queueStore.clear(),this.logger("(release queue)",o),o.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}return e},Object.defineProperties(e.prototype,r),e}(u))));exports.ALL_EVT="all",exports.AVAILABLE_EVTS=h,exports.CLEAR_EVT="clear",exports.DELETE_EVT="delete",exports.GET_EVT="get",exports.HAS_EVT="has",exports.JsonqlStore=p,exports.SET_EVT="set",exports.SIZE_EVT="size",exports.TAKE_EVT="take";
+//# sourceMappingURL=jsonql-store.cjs.js.map
diff --git a/packages/@jsonql/store/dist/jsonql-store.cjs.js.map b/packages/@jsonql/store/dist/jsonql-store.cjs.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..7bc96c24952125d48cfd30b7d572b678774cd846
--- /dev/null
+++ b/packages/@jsonql/store/dist/jsonql-store.cjs.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"jsonql-store.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/packages/@jsonql/store/dist/jsonql-store.umd.js b/packages/@jsonql/store/dist/jsonql-store.umd.js
new file mode 100644
index 0000000000000000000000000000000000000000..2cce530033326fc4193604856c349b6e0441e314
--- /dev/null
+++ b/packages/@jsonql/store/dist/jsonql-store.umd.js
@@ -0,0 +1,2 @@
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).jsonqlStore={})}(this,(function(t){"use strict";var e="You are trying to register an event already been taken by other type:",r=["on","only","once","onlyOnce"],o=["on","only"];function n(t){return t instanceof RegExp}function i(t){return"string"==typeof t}function s(t){if(i(t))throw new Error("Wrong type, we want number!");return!isNaN(parseInt(t))}var a=new WeakMap,u=new WeakMap,l=function(){},h={$name:{configurable:!0},is:{configurable:!0}};l.prototype.logger=function(){},h.$name.get=function(){return"to1source-event"},h.is.get=function(){return this.$name},l.prototype.validateEvt=function(){for(var t=this,e=[],r=arguments.length;r--;)e[r]=arguments[r];return e.forEach((function(e){if(!i(e))throw t.logger("(validateEvt)",e),new Error("Event name must be string type! we got "+typeof e)})),!0},l.prototype.validate=function(t,e){if(this.validateEvt(t)&&"function"==typeof e)return!0;throw new Error("callback required to be function type! we got "+typeof e)},l.prototype.validateType=function(t){return this.validateEvt(t),!!r.filter((function(e){return t===e})).length},l.prototype.run=function(t,e,r){return this.logger("(run) callback:",t,"payload:",e,"context:",r),this.$done=Reflect.apply(t,r,this.toArray(e)),this.$done},l.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,e){return(t=(t<<5)-t+e.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(l.prototype,h);var p=["has","set","get","delete","take","all","size","clear"],g=function(t){function e(e){void 0===e&&(e={}),t.call(this,e),this.$store=new Map}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={length:{configurable:!0}};return e.prototype.has=function(t){var e=this.$store.has(t)||!1;return this.$trigger("has",[t,e]),e},e.prototype.set=function(t,e){return this.$store.set(t,e),this.$trigger("set",[t,e]),this.has(t)},e.prototype.get=function(t){var e=this.$store.get(t)||!1;return this.$trigger("get",[t,e]),e},e.prototype.delete=function(t){var e=this.$store.delete(t);return this.$trigger("delete",[t,e]),e},e.prototype.take=function(t){if(this.has(t)){var e=this.$store.get(t);return this.$trigger("take",[t,e]),this.$store.delete(t),e}return this.$trigger("take",[t]),!1},e.prototype.all=function(t){void 0===t&&(t=!1);var e=this.$store.entries(),r=t?Array.from(e):e;return this.$trigger("all",[r]),r},e.prototype.size=function(){var t=this.$store.size;return this.$trigger("size",[t]),t},r.length.get=function(){return this.size()},e.prototype.clear=function(){this.$store.clear(),this.$trigger("clear")},e.prototype.on=function(t,e,r){if(void 0===r&&(r=null),!!p.filter((function(e){return e===t})).length)return this.$on(t,e,r);throw new Error(t+" is not one of ours!")},Object.defineProperties(e.prototype,r),e}(function(t){function r(e){void 0===e&&(e={}),t.call(this,e)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var o={$done:{configurable:!0}};return r.prototype.$on=function(t,r,o){var n=this;void 0===o&&(o=null);this.validate(t,r);var i=this.takeFromStore(t);if(!1===i)return this.logger('($on) "'+t+'" is not in lazy store'),this.addToNormalStore(t,"on",r,o);this.logger("($on) "+t+" found in lazy store");var s=0;return i.forEach((function(i){var a=i[0],u=i[1],l=i[2];if(l&&"on"!==l)throw new Error(e+" "+l);n.logger("($on)",'call run "'+t+'"'),n.run(r,a,o||u),s+=n.addToNormalStore(t,"on",r,o||u)})),this.logger("($on) return size "+s),s},r.prototype.$once=function(t,r,o){void 0===o&&(o=null),this.validate(t,r);var n=this.takeFromStore(t);if(!1===n)return this.logger('($once) "'+t+'" is not in the lazy store'),this.addToNormalStore(t,"once",r,o);this.logger("($once)",n);var i=Array.from(n)[0],s=i[0],a=i[1],u=i[2];if(u&&"once"!==u)throw new Error(e+" "+u);this.logger("($once)",'call run "'+t+'"'),this.run(r,s,o||a),this.$off(t)},r.prototype.$only=function(t,r,o){var n=this;void 0===o&&(o=null),this.validate(t,r);var i=!1,s=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger('($only) "'+t+'" add to normalStore'),i=this.addToNormalStore(t,"only",r,o)),!1!==s)&&(this.logger('($only) "'+t+'" found data in lazy store to execute'),Array.from(s).forEach((function(i){var s=i[0],a=i[1],u=i[2];if(u&&"only"!==u)throw new Error(e+" "+u);n.logger('($only) call run "'+t+'"'),n.run(r,s,o||a)})));return i},r.prototype.$onlyOnce=function(t,r,o){void 0===o&&(o=null),this.validate(t,r);var n=!1,i=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger('($onlyOnce) "'+t+'" add to normalStore'),n=this.addToNormalStore(t,"onlyOnce",r,o)),!1!==i){this.logger("($onlyOnce)",i);var s=Array.from(i)[0],a=s[0],u=s[1],l=s[2];if(l&&"onlyOnce"!==l)throw new Error(e+" "+l);this.logger('($onlyOnce) call run "'+t+'"'),this.run(r,a,o||u),this.$off(t)}return n},r.prototype.$max=function(t,e,r){if(void 0===r&&(r=null),this.validateEvt(t),s(e)&&e>0){if(!1!==this.$get(t,!0)){var o=this.searchMapEvt(t);if(o.length){var n=o[0][3],i=(this.checkMaxStore(t,e),this);return function(){for(var e=[],o=arguments.length;o--;)e[o]=arguments[o];var s=i.getMaxStore(t),a=-1;if(s>0){var u=i.$call(t,n,r);if(Reflect.apply(u,i,e),-1===(a=i.checkMaxStore(t)))return i.$off(t),-1}return a}}}return this.logger("The "+t+" is not registered, can not execute non-existing event at the moment"),-1}throw new Error("Expect max to be an integer and greater than zero! But we got ["+typeof e+"]"+e+" instead")},r.prototype.$replace=function(t,e,r,o){if(void 0===r&&(r=null),void 0===o&&(o="on"),this.validateType(o)){this.$off(t);var n=this["$"+o];return this.logger("($replace)",t,e),Reflect.apply(n,this,[t,e,r])}throw new Error(o+" is not supported!")},r.prototype.$trigger=function(t,e,r,o){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===o&&(o=!1),this.validateEvt(t);var n=0,i=this.normalStore;if(this.logger("($trigger) normalStore",i),i.has(t)){if(this.logger('($trigger) "'+t+'" found'),this.$queue(t,e,r,o))return this.logger('($trigger) Currently suspended "'+t+'" added to queue, nothing executed. Exit now.'),!1;for(var s=Array.from(i.get(t)),a=s.length,u=!1,l=0;l0&&--r,!(r>0))return this.maxCountStore.delete(t),this.logger("remove "+t+" from maxStore"),-1;this.maxCountStore.set(t,r)}return r}throw new Error("Expect max to be an integer, but we got "+typeof e+" "+e)},e.prototype.searchMapEvt=function(t){var e=this.$get(t,!0).filter((function(t){var e,r=t[3];return e=r,!!o.filter((function(t){return e===t})).length}));return e.length?e:[]},e.prototype.takeFromStore=function(t,e){void 0===e&&(e="lazyStore");var r=this[e];if(r){if(this.logger("(takeFromStore)",e,r),r.has(t)){var o=r.get(t);return this.logger('(takeFromStore) has "'+t+'"',o),r.delete(t),o}return!1}throw new Error('"'+e+'" is not supported!')},e.prototype.findFromStore=function(t,e,r){return void 0===r&&(r=!1),!!e.has(t)&&Array.from(e.get(t)).map((function(t){return r?t:t[1]}))},e.prototype.removeFromStore=function(t,e){return!!e.has(t)&&(this.logger("($off)",t),e.delete(t),!0)},e.prototype.getStoreSet=function(t,e){var r;return t.has(e)?(this.logger('(addToStore) "'+e+'" existed'),r=t.get(e)):(this.logger('(addToStore) create new Set for "'+e+'"'),r=new Set),r},e.prototype.addToStore=function(t,e){for(var r=[],o=arguments.length-2;o-- >0;)r[o]=arguments[o+2];var n=this.getStoreSet(t,e);if(r.length>2)if(Array.isArray(r[0])){var i=r[2];this.checkTypeInLazyStore(e,i)||n.add(r)}else this.checkContentExist(r,n)||(this.logger("(addToStore) insert new",r),n.add(r));else n.add(r);return t.set(e,n),[t,n.size]},e.prototype.checkContentExist=function(t,e){return!!Array.from(e).filter((function(e){return e[0]===t[0]})).length},e.prototype.checkTypeInStore=function(t,e){this.validateEvt(t,e);var r=this.$get(t,!0);return!1===r||!r.filter((function(t){var r=t[3];return e!==r})).length},e.prototype.checkTypeInLazyStore=function(t,e){this.validateEvt(t,e);var r=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",r),!!r&&!!Array.from(r).filter((function(t){return t[2]!==e})).length},e.prototype.addToNormalStore=function(t,e,r,o){if(void 0===o&&(o=null),this.logger('(addToNormalStore) try to add "'+e+'" --\x3e "'+t+'" to normal store'),this.checkTypeInStore(t,e)){this.logger("(addToNormalStore)",'"'+e+'" --\x3e "'+t+'" can add to normal store');var n=this.hashFnToKey(r),i=[this.normalStore,t,n,r,o,e],s=Reflect.apply(this.addToStore,this,i),a=s[0],u=s[1];return this.normalStore=a,u}return!1},e.prototype.addToLazyStore=function(t,e,r,o){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===o&&(o=!1);var n=[this.lazyStore,t,this.toArray(e),r];o&&n.push(o);var i=Reflect.apply(this.addToStore,this,n),s=i[0],a=i[1];return this.lazyStore=s,this.logger("(addToLazyStore) size: "+a),a},e.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},r.normalStore.set=function(t){a.set(this,t)},r.normalStore.get=function(){return a.get(this)},r.lazyStore.set=function(t){u.set(this,t)},r.lazyStore.get=function(){return u.get(this)},Object.defineProperties(e.prototype,r),e}(function(t){function e(){t.call(this),this.__suspend_state__=null,this.__pattern__=null,this.queueStore=new Set}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={$queues:{configurable:!0}};return e.prototype.$suspend=function(){this.logger("---\x3e SUSPEND ALL OPS <---"),this.__suspend__(!0)},e.prototype.$release=function(){this.logger("---\x3e RELEASE SUSPENDED QUEUE <---"),this.__suspend__(!1)},e.prototype.$suspendEvent=function(t){var e=function(t){switch(!0){case!0===n(t):return t;case!0===i(t):return new RegExp(t);default:return!1}}(t);if(n(e))return this.__pattern__=e,this.$suspend();throw new Error('We expect a pattern variable to be string or RegExp, but we got "'+typeof e+'" instead')},e.prototype.$queue=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];if(this.logger("($queue) get called"),!0===this.__suspend_state__){if(n(this.__pattern__)){var o=this.__pattern__.test(t);if(!o)return!1}this.logger("($queue) added to $queue",e),this.queueStore.add([t].concat(e))}return!!this.__suspend_state__},r.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},e.prototype.__suspend__=function(t){if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value! we got "+typeof t);var e=this.__suspend_state__;this.__suspend_state__=t,this.logger('($suspend) Change from "'+e+'" --\x3e "'+t+'"'),!0===e&&!1===t&&this.__release__()},e.prototype.__release__=function(){var t=this,e=this.queueStore.size,r=this.__pattern__;if(this.__pattern__=null,this.logger("(release) was called with "+e+(r?' for "'+r+'"':"")+" item"+(e>1?"s":"")),e>0){var o=Array.from(this.queueStore);this.queueStore.clear(),this.logger("(release queue)",o),o.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}return e},Object.defineProperties(e.prototype,r),e}(l))));t.ALL_EVT="all",t.AVAILABLE_EVTS=p,t.CLEAR_EVT="clear",t.DELETE_EVT="delete",t.GET_EVT="get",t.HAS_EVT="has",t.JsonqlStore=g,t.SET_EVT="set",t.SIZE_EVT="size",t.TAKE_EVT="take",Object.defineProperty(t,"__esModule",{value:!0})}));
+//# sourceMappingURL=jsonql-store.umd.js.map
diff --git a/packages/@jsonql/store/dist/jsonql-store.umd.js.map b/packages/@jsonql/store/dist/jsonql-store.umd.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..72ab55120370ac3208059fb40c32094582d1dc05
--- /dev/null
+++ b/packages/@jsonql/store/dist/jsonql-store.umd.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"jsonql-store.umd.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/packages/@jsonql/store/index.js b/packages/@jsonql/store/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..5e903cc9bfb6295b6d4b2c37824eb02b910df9c1
--- /dev/null
+++ b/packages/@jsonql/store/index.js
@@ -0,0 +1,26 @@
+import { JsonqlStore } from './src/jsonql-store-class'
+import {
+ HAS_EVT,
+ SET_EVT,
+ GET_EVT,
+ DELETE_EVT,
+ TAKE_EVT,
+ ALL_EVT,
+ SIZE_EVT,
+ CLEAR_EVT,
+ AVAILABLE_EVTS
+} from './src/constants'
+
+export {
+ JsonqlStore,
+ // all events
+ HAS_EVT,
+ SET_EVT,
+ GET_EVT,
+ DELETE_EVT,
+ TAKE_EVT,
+ ALL_EVT,
+ SIZE_EVT,
+ CLEAR_EVT,
+ AVAILABLE_EVTS
+}
\ No newline at end of file
diff --git a/packages/@jsonql/store/package.json b/packages/@jsonql/store/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..6fd4a27c2cba4c4f446a70534c1b81e01448c47a
--- /dev/null
+++ b/packages/@jsonql/store/package.json
@@ -0,0 +1,75 @@
+{
+ "name": "@jsonql/store",
+ "version": "0.9.0",
+ "description": "A super simple in-memory key value store also provide a event hook for you to hook into the storage of your choice",
+ "main": "dist/jsonql-store.cjs.js",
+ "browser": "dist/jsonql-store.umd.js",
+ "module": "index.js",
+ "scripts": {
+ "test": "ava",
+ "prepare": "npm run build && npm run test",
+ "build": "NODE_ENV=production npm run build:cjs && NODE_ENV=production npm run build:umd",
+ "build:cjs": "TARGET=cjs rollup -c",
+ "build:umd": "TARGET=umd rollup -c",
+ "test:basic": "DEBUG=jsonql-store* ava ./tests/basic.test.js",
+ "test:event": "DEBUG=jsonql-store* ava ./tests/event.test.js"
+ },
+ "keywords": [
+ "store",
+ "in-memory",
+ "event",
+ "hooks",
+ "storage",
+ "key",
+ "value"
+ ],
+ "author": "Joel Chu ",
+ "license": "ISC",
+ "dependencies": {
+ "@to1source/event": "^1.1.1"
+ },
+ "homepage": "https://jsonql.org",
+ "devDependencies": {
+ "ava": "^3.5.1",
+ "debug": "^4.1.1",
+ "esm": "^3.2.25",
+ "rollup": "^2.2.0",
+ "rollup-plugin-alias": "^2.2.0",
+ "rollup-plugin-async": "^1.2.0",
+ "rollup-plugin-buble": "^0.19.8",
+ "rollup-plugin-bundle-size": "^1.0.3",
+ "rollup-plugin-commonjs": "^10.1.0",
+ "rollup-plugin-copy": "^3.3.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.2.0",
+ "rollup-plugin-replace": "^2.2.0",
+ "rollup-plugin-serve": "^1.0.1",
+ "rollup-plugin-terser": "^5.3.0"
+ },
+ "ava": {
+ "files": [
+ "tests/**/*.test.js"
+ ],
+ "ignoredByWatcher": [
+ "tests/fixtures/**/*.*"
+ ],
+ "require": [
+ "esm"
+ ],
+ "cache": true,
+ "concurrency": 5,
+ "failFast": true,
+ "failWithoutAssertions": false,
+ "tap": false,
+ "verbose": true
+ },
+ "engine": {
+ "node": ">=8"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@gitee.com:to1source/jsonql.git"
+ }
+}
diff --git a/packages/@jsonql/store/rollup.config.js b/packages/@jsonql/store/rollup.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..71d36a0bd4319faff1bab31d24c3ddd4a3e2315e
--- /dev/null
+++ b/packages/@jsonql/store/rollup.config.js
@@ -0,0 +1,74 @@
+/**
+ * Rollup config for building the client package
+ */
+import { join } from 'path'
+import buble from 'rollup-plugin-buble'
+
+import { terser } from "rollup-plugin-terser"
+import replace from 'rollup-plugin-replace'
+import commonjs from 'rollup-plugin-commonjs'
+
+import json from 'rollup-plugin-json'
+
+import nodeResolve from 'rollup-plugin-node-resolve'
+import nodeGlobals from 'rollup-plugin-node-globals'
+import builtins from 'rollup-plugin-node-builtins'
+import size from 'rollup-plugin-bundle-size'
+// support async functions
+import async from 'rollup-plugin-async'
+// get the version info
+import { version } from './package.json'
+
+const env = process.env.NODE_ENV
+const target = process.env.TARGET
+
+let plugins = [
+ json({
+ preferConst: true
+ }),
+ buble({
+ objectAssign: 'Object.assign'
+ }),
+ nodeResolve({ preferBuiltins: true }),
+ commonjs({
+ include: 'node_modules/**'
+ }),
+ nodeGlobals(),
+ builtins(),
+ async(),
+ replace({
+ 'process.env.NODE_ENV': JSON.stringify('production'),
+ '__PLACEHOLDER__': `version: ${version} module: UMD`
+ })
+]
+
+if (env === 'production') {
+ plugins.push(terser())
+}
+plugins.push(size())
+
+let config = {
+ input: join(__dirname, 'index.js'),
+ output: {
+ name: 'jsonqlStore',
+ file: join(__dirname, 'dist', `jsonql-store.${target}.js`),
+ format: target,
+ sourcemap: true,
+ globals: {
+ 'socket.io-client': 'io',
+ 'promise-polyfill': 'Promise',
+ 'debug': 'debug'
+ }
+ },
+ external: [
+ 'WebSocket',
+ 'socket.io-client',
+ 'io',
+ 'debug',
+ 'Promise',
+ 'promise-polyfill'
+ ],
+ plugins: plugins
+};
+
+export default config
diff --git a/packages/@jsonql/store/src/constants.js b/packages/@jsonql/store/src/constants.js
new file mode 100644
index 0000000000000000000000000000000000000000..eb75f1da6f3b1bc813d5f9adae54915b9c514d46
--- /dev/null
+++ b/packages/@jsonql/store/src/constants.js
@@ -0,0 +1,22 @@
+
+// create constants for all the event names
+// 'has', 'set', 'get', 'remove', 'take', 'all', 'size'
+export const HAS_EVT = 'has'
+export const SET_EVT = 'set'
+export const GET_EVT = 'get'
+export const DELETE_EVT = 'delete'
+export const TAKE_EVT = 'take'
+export const ALL_EVT = 'all'
+export const SIZE_EVT = 'size'
+export const CLEAR_EVT = 'clear'
+
+export const AVAILABLE_EVTS = [
+ HAS_EVT,
+ SET_EVT,
+ GET_EVT,
+ DELETE_EVT,
+ TAKE_EVT,
+ ALL_EVT,
+ SIZE_EVT,
+ CLEAR_EVT
+]
\ No newline at end of file
diff --git a/packages/@jsonql/store/src/jsonql-store-class.js b/packages/@jsonql/store/src/jsonql-store-class.js
new file mode 100644
index 0000000000000000000000000000000000000000..e18dccb51ef5b6ed21a058961c2eb692e6898e0c
--- /dev/null
+++ b/packages/@jsonql/store/src/jsonql-store-class.js
@@ -0,0 +1,154 @@
+// just fucking around with the cache object
+// NodeCache is a piece of shit
+import EventClass from '@to1source/event'
+import {
+ HAS_EVT,
+ SET_EVT,
+ GET_EVT,
+ DELETE_EVT,
+ TAKE_EVT,
+ ALL_EVT,
+ SIZE_EVT,
+ CLEAR_EVT,
+ AVAILABLE_EVTS
+} from './constants'
+
+
+export class JsonqlStore extends EventClass {
+
+ /**
+ * constructor init the instance
+ * @param {*} opts
+ */
+ constructor(opts = {}) {
+ super(opts)
+ this.$store = new Map()
+ }
+
+ /**
+ * Check key exist
+ * @param {*} key
+ * @return {*}
+ */
+ has(key) {
+ const result = this.$store.has(key) || false
+ this.$trigger(HAS_EVT, [key, result])
+
+ return result
+ }
+
+ /**
+ * note this actually return the value itself
+ * @param {*} key
+ * @param {*} value
+ * @return {*}
+ */
+ set(key, value) {
+ this.$store.set(key, value)
+ this.$trigger(SET_EVT, [key, value])
+
+ return this.has(key)
+ }
+
+ /**
+ * get it and make sure it return boolen false when nothing
+ * @param {*} key
+ * @return {*}
+ */
+ get(key) {
+ const result = this.$store.get(key) || false
+ this.$trigger(GET_EVT, [key, result])
+
+ return result
+ }
+
+ /**
+ * Remove from store
+ * @param {*} key
+ * @return {*}
+ */
+ delete(key) {
+ const result = this.$store.delete(key)
+ this.$trigger(DELETE_EVT, [key, result])
+
+ return result
+ }
+
+ /**
+ * return the key value then remove it
+ * @param {*} key
+ * @return {*}
+ */
+ take(key) {
+ if (this.has(key)) {
+ const value = this.$store.get(key)
+ this.$trigger(TAKE_EVT, [key, value])
+ // we call the native method because we don't want to trigger the delete event again
+ this.$store.delete(key)
+ return value
+ }
+ this.$trigger(TAKE_EVT, [key])
+ return false
+ }
+
+ /**
+ * alias to entries return interable object
+ * @param {boolean} arr return as array or not
+ * @return {array}
+ */
+ all(arr = false) {
+ const result = this.$store.entries()
+ const returnResult = arr ? Array.from(result) : result
+
+ this.$trigger(ALL_EVT, [returnResult])
+
+ return returnResult
+ }
+
+ /**
+ * Get the size (length) of the store
+ * @return {number}
+ */
+ size() {
+ const result = this.$store.size
+ this.$trigger(SIZE_EVT, [result])
+
+ return result
+ }
+
+ /**
+ * Alias to size as a getter
+ * @return {number}
+ */
+ get length() {
+ return this.size()
+ }
+
+ /**
+ * Clear out everything from store
+ * @return {void}
+ */
+ clear() {
+ this.$store.clear()
+ this.$trigger(CLEAR_EVT)
+ // @TODO should we clear out all the event listeners as well?
+ }
+
+ /**
+ * event hook
+ * @param {string} evtName
+ * @param {function} callback
+ * @param {*} context
+ * @return {*}
+ */
+ on(evtName, callback, context = null) {
+ const ok = !!AVAILABLE_EVTS.filter(e => e === evtName).length
+ if (ok) {
+ return this.$on(evtName, callback, context)
+ }
+ throw new Error(`${evtName} is not one of ours!`)
+ }
+
+}
+
+
diff --git a/packages/@jsonql/store/tests/basic.test.js b/packages/@jsonql/store/tests/basic.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..420237d8c58e2631fd1bb336984fc983f1c5df75
--- /dev/null
+++ b/packages/@jsonql/store/tests/basic.test.js
@@ -0,0 +1,92 @@
+const test = require('ava')
+
+const { JsonqlStore } = require('../index')
+const debug = require('debug')('jsonql-store:test:basic')
+
+test.before(t => {
+ t.context.store = new JsonqlStore({ logger: debug })
+})
+
+
+test(`It should able to store anything using a key`, t => {
+ const store = t.context.store
+ const someKey = 'some-key'
+ const someValue = {msg: 'Store an object and check the content later'}
+
+ const result = store.set(someKey, someValue)
+ t.true(result)
+
+ const value = store.get(someKey)
+
+ t.deepEqual(someValue, value)
+})
+
+
+test(`It should able to store a function and return it still a function`, t => {
+
+ const store = t.context.store
+
+ const key = 'some-fn-key'
+ const fn = function(msg) {
+ return `got your ${msg}`
+ }
+
+ const result = store.set(key, fn)
+ t.true(result)
+
+ const fn1 = store.get(key)
+ t.true(typeof fn1 === 'function')
+ t.true(fn1('na na na').indexOf('na na na') > -1)
+
+ const fn2 = store.get(key)
+
+ t.true(typeof fn2 === 'function')
+ // check size
+
+ const size = store.size()
+
+ debug('size', size)
+ t.truthy(size)
+
+ store.clear()
+
+ const size1 = store.size()
+
+ t.is(size1, 0)
+
+})
+
+
+test(`Test the rest of the methods take, delete, all etc`, t => {
+ const store = t.context.store
+ const someKey = 'some-key'
+ const someValue = 'some-value'
+
+ const someKey1 = 'some-key-1'
+ const someValue1 = 'some-value-1'
+
+ store.set(someKey, someValue)
+ store.set(someKey1, someValue1)
+
+ const size = store.size()
+
+ t.is(size, 2)
+
+ const arr = store.all()
+ const arr1 = store.all(true)
+ debug('all', arr)
+ debug('array', arr1)
+
+ store.delete(someKey)
+
+ const check = store.has(someKey)
+
+ t.false(check)
+
+ const value2 = store.take(someKey1)
+
+ t.is(value2, someValue1)
+
+ t.is(store.size(), 0)
+
+})
\ No newline at end of file
diff --git a/packages/@jsonql/store/tests/event.test.js b/packages/@jsonql/store/tests/event.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..145528c367958ac643804e150df36be152afaab3
--- /dev/null
+++ b/packages/@jsonql/store/tests/event.test.js
@@ -0,0 +1,113 @@
+// this will focus on the event hook testing
+
+const test = require('ava')
+const {
+ JsonqlStore,
+ HAS_EVT,
+ SET_EVT,
+ GET_EVT,
+ DELETE_EVT,
+ TAKE_EVT,
+ ALL_EVT,
+ SIZE_EVT,
+ CLEAR_EVT
+} = require('../dist/jsonql-store.cjs')
+const debug = require('debug')('jsonql-store:test:event')
+const Event = require('@to1source/event')
+
+test.before(t => {
+ t.context.store = new JsonqlStore({ logger: debug })
+ t.context.event = new Event()
+})
+
+test.cb(`It should able to hook into the store using the on method`, t => {
+
+ t.plan(2)
+
+ const store = t.context.store
+
+ // we add the on before calling it
+ store.on(SET_EVT, function(...args) {
+ debug(SET_EVT, args)
+ t.pass()
+ })
+
+ store.on(GET_EVT, function() {
+ t.pass()
+ t.end()
+ })
+
+ const somekey1 = 'key-1'
+ const someval1 = 'value-1'
+
+ store.set(somekey1, someval1)
+
+ store.get(somekey1)
+})
+
+test.cb(`Test all the event hooks`, t => {
+ const total = 7
+ t.plan(total)
+ let ctn = 0
+ // listen to the count
+ const evt = t.context.event
+ const store = new JsonqlStore()
+ evt.$on('add', function(type) {
+ ++ctn
+ debug('ctn -------------------->', ctn, type)
+ if (ctn >= total) {
+ t.end()
+ }
+ })
+ const add = (type) => evt.$trigger('add', [type])
+
+ const somekey2 = 'key-2'
+ const someval2 = 'value-2'
+
+ const somekey3 = 'key-3'
+ const someval3 = 'value-3'
+
+ store.set(somekey2, someval2)
+ store.set(somekey3, someval3)
+
+ store.all(true)
+
+ store.delete(somekey2)
+ store.take(somekey3)
+ store.size()
+
+ store.clear()
+
+ store.on(SET_EVT, function(...args) {
+ debug(SET_EVT, args)
+ t.pass()
+ add(SET_EVT)
+ })
+
+ store.on(DELETE_EVT, function() {
+ t.pass()
+ add(DELETE_EVT)
+ })
+
+ store.on(TAKE_EVT, function() {
+ t.pass()
+ add(TAKE_EVT)
+ })
+
+ store.on(SIZE_EVT, function() {
+ t.pass()
+ add(SIZE_EVT)
+ })
+
+ store.on(ALL_EVT, function(values) {
+ debug(values)
+ t.pass()
+ add(ALL_EVT)
+ })
+
+ store.on(CLEAR_EVT, function() {
+ t.pass()
+ add(CLEAR_EVT)
+ })
+
+})
diff --git a/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js b/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js
index b0f3746a6fe75c0e396da1ce2e96f9d788f88dce..252d36824cbdf5875b80a019a45100b013c37f09 100644
--- a/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js
+++ b/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js
@@ -1,2 +1,2 @@
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).jsonqlWsClient=e()}(this,(function(){"use strict";var t=Array.isArray,e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},r="object"==typeof e&&e&&e.Object===Object&&e,n="object"==typeof self&&self&&self.Object===Object&&self,o=r||n||Function("return this")(),i=o.Symbol,a=Object.prototype,u=a.hasOwnProperty,c=a.toString,s=i?i.toStringTag:void 0;var f=Object.prototype.toString;var l=i?i.toStringTag:void 0;function p(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":l&&l in Object(t)?function(t){var e=u.call(t,s),r=t[s];try{t[s]=void 0;var n=!0}catch(t){}var o=c.call(t);return n&&(e?t[s]=r:delete t[s]),o}(t):function(t){return f.call(t)}(t)}function h(t,e){return function(r){return t(e(r))}}var v=h(Object.getPrototypeOf,Object);function d(t){return null!=t&&"object"==typeof t}var g=Function.prototype,y=Object.prototype,_=g.toString,b=y.hasOwnProperty,m=_.call(Object);function j(t){if(!d(t)||"[object Object]"!=p(t))return!1;var e=v(t);if(null===e)return!0;var r=b.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&_.call(r)==m}function w(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var i=Array(o);++n-1;);return r}(n,o),function(t,e){for(var r=t.length;r--&&T(e,t[r],0)>-1;);return r}(n,o)+1).join("")}var B=function(e){return t(e)?e:[e]},H=function(t,e){void 0===e&&(e=!0);try{return JSON.parse(t)}catch(r){if(e)return t;throw new Error(r)}},G=function(t,e){try{var r=Object.keys(t);return n=e,!!r.filter((function(t){return t===n})).length}catch(t){return!1}var n},V=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return t.join("_")},Y=function(t){return H("string"==typeof t?t:JSON.stringify(t))},K=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},Q=function(){return!1},X=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return Reflect.apply(e,null,B(t))}),Reflect.apply(t,null,r))}};function Z(t,e){return t===e||t!=t&&e!=e}function tt(t,e){for(var r=t.length;r--;)if(Z(t[r][0],e))return r;return-1}var et=Array.prototype.splice;function rt(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1},rt.prototype.set=function(t,e){var r=this.__data__,n=tt(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};function ot(t){if(!nt(t))return!1;var e=p(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}var it,at=o["__core-js_shared__"],ut=(it=/[^.]+$/.exec(at&&at.keys&&at.keys.IE_PROTO||""))?"Symbol(src)_1."+it:"";var ct=Function.prototype.toString;function st(t){if(null!=t){try{return ct.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var ft=/^\[object .+?Constructor\]$/,lt=Function.prototype,pt=Object.prototype,ht=lt.toString,vt=pt.hasOwnProperty,dt=RegExp("^"+ht.call(vt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function gt(t){return!(!nt(t)||(e=t,ut&&ut in e))&&(ot(t)?dt:ft).test(st(t));var e}function yt(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return gt(r)?r:void 0}var _t=yt(o,"Map"),bt=yt(Object,"create");var mt=Object.prototype.hasOwnProperty;var jt=Object.prototype.hasOwnProperty;function wt(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&t<=9007199254740991}function Gt(t){return null!=t&&Ht(t.length)&&!ot(t)}var Vt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Yt=Vt&&"object"==typeof module&&module&&!module.nodeType&&module,Kt=Yt&&Yt.exports===Vt?o.Buffer:void 0,Qt=(Kt?Kt.isBuffer:void 0)||function(){return!1},Xt={};Xt["[object Float32Array]"]=Xt["[object Float64Array]"]=Xt["[object Int8Array]"]=Xt["[object Int16Array]"]=Xt["[object Int32Array]"]=Xt["[object Uint8Array]"]=Xt["[object Uint8ClampedArray]"]=Xt["[object Uint16Array]"]=Xt["[object Uint32Array]"]=!0,Xt["[object Arguments]"]=Xt["[object Array]"]=Xt["[object ArrayBuffer]"]=Xt["[object Boolean]"]=Xt["[object DataView]"]=Xt["[object Date]"]=Xt["[object Error]"]=Xt["[object Function]"]=Xt["[object Map]"]=Xt["[object Number]"]=Xt["[object Object]"]=Xt["[object RegExp]"]=Xt["[object Set]"]=Xt["[object String]"]=Xt["[object WeakMap]"]=!1;var Zt,te="object"==typeof exports&&exports&&!exports.nodeType&&exports,ee=te&&"object"==typeof module&&module&&!module.nodeType&&module,re=ee&&ee.exports===te&&r.process,ne=function(){try{var t=ee&&ee.require&&ee.require("util").types;return t||re&&re.binding&&re.binding("util")}catch(t){}}(),oe=ne&&ne.isTypedArray,ie=oe?(Zt=oe,function(t){return Zt(t)}):function(t){return d(t)&&Ht(t.length)&&!!Xt[p(t)]};function ae(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var ue=Object.prototype.hasOwnProperty;function ce(t,e,r){var n=t[e];ue.call(t,e)&&Z(n,r)&&(void 0!==r||e in t)||$t(t,e,r)}var se=/^(?:0|[1-9]\d*)$/;function fe(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&se.test(t))&&t>-1&&t%1==0&&t0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(we);function Ee(t,e){return Se(function(t,e,r){return e=je(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,i=je(n.length-e,0),a=Array(i);++o1?e[n-1]:void 0,i=n>2?e[2]:void 0;for(o=ke.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,e,r){if(!nt(r))return!1;var n=typeof e;return!!("number"==n?Gt(r)&&fe(e,r.length):"string"==n&&e in r)&&Z(r[e],t)}(e[0],e[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++r0))},ar=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var e=t.replace("array.<","").replace(">","");return e.indexOf("|")?e.split("|"):[e]}return!1},ur=function(t,e){var r=t.arg;return e.length>1?!r.filter((function(t){return!(e.length>e.filter((function(e){return!or(e)(t)})).length)})).length:e.length>e.filter((function(t){return!ir(r,t)})).length},cr=function(t,e){if(void 0===e&&(e=null),j(t)){if(!e)return!0;if(ir(e))return!e.filter((function(e){var r=t[e.name];return!(e.type.length>e.type.filter((function(t){var e;return void 0===r||(!1!==(e=ar(t))?!ur({arg:r},e):!or(t)(r))})).length)})).length}return!1},sr=function(t,e){var r,n,o,i,a;switch(!0){case"object"===t:return o=(n=e).arg,i=n.param,a=[o],Array.isArray(i.keys)&&i.keys.length&&a.push(i.keys),!Reflect.apply(cr,null,a);case"array"===t:return!ir(e.arg);case!1!==(r=ar(t)):return!ur(e,r);default:return!or(t)(e.arg)}},fr=function(t,e){return void 0!==t?t:!0===e.optional&&void 0!==e.defaultvalue?e.defaultvalue:null},lr=function(t,e,r){var n;void 0===r&&(r=!1);var o=function(t,e){if(!ir(e))throw new Je("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===e.length)return[];if(!ir(t))throw new Je("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==e.length:return t.map((function(t,r){return{arg:t,index:r,param:e[r]}}));case!0===e[0].variable:var r=e[0].type;return t.map((function(t,n){return{arg:t,index:n,param:e[n]||{type:r,name:"_"}}}));case t.lengthe.length:var n=e.length,o=["any"];return t.map((function(t,r){var i=r>=n||!!e[r].optional,a=e[r]||{type:o,name:"_"+r};return{arg:i?fr(t,a):t,index:r,param:a,optional:i}}));default:throw new We("Could not understand your arguments and parameter structure!",{args:t,params:e})}}(t,e),i=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var e=t.arg,r=t.param;return!!Xe(e)&&!(r.type.length>r.type.filter((function(e){return sr(e,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(e){return sr(e,t)})).length)}));return r?((n={}).error=i,n.data=o.map((function(t){return t.arg})),n):i},pr=h(Object.keys,Object),hr=Object.prototype.hasOwnProperty;function vr(t){return Gt(t)?pe(t):function(t){if(!Jt(t))return pr(t);var e=[];for(var r in Object(t))hr.call(t,r)&&"constructor"!=r&&e.push(r);return e}(t)}function dr(t,e){return t&&xt(t,e,vr)}function gr(t){var e=-1,r=null==t?0:t.length;for(this.__data__=new St;++eu))return!1;var s=i.get(t);if(s&&i.get(e))return s==e;var f=-1,l=!0,p=2&r?new gr:void 0;for(i.set(t,e),i.set(e,t);++f0;)e[r]=arguments[r+1];if(this.logger("($queue) get called"),!0===this.__suspend_state__){if(Pn(this.__pattern__)){var n=this.__pattern__.test(t);if(!n)return!1}this.logger("($queue) added to $queue",e),this.queueStore.add([t].concat(e))}return!!this.__suspend_state__},Cn.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},Nn.prototype.__suspend__=function(t){if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value! we got "+typeof t);var e=this.__suspend_state__;this.__suspend_state__=t,this.logger('($suspend) Change from "'+e+'" --\x3e "'+t+'"'),!0===e&&!1===t&&this.__release__()},Nn.prototype.__release__=function(){var t=this,e=this.queueStore.size,r=this.__pattern__;if(this.__pattern__=null,this.logger("(release) was called with "+e+(r?' for "'+r+'"':"")+" item"+(e>1?"s":"")),e>0){var n=Array.from(this.queueStore);this.queueStore.clear(),this.logger("(release queue)",n),n.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}return e},Object.defineProperties(Nn.prototype,Cn);var Rn=function(t){function e(e){if("function"!=typeof e)throw new Error("Just die here the logger is not a function!");e("---\x3e Create a new EventEmitter <---"),t.call(this,{logger:e})}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(e.prototype,r),e}(function(t){function e(e){void 0===e&&(e={}),t.call(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={$name:{configurable:!0},is:{configurable:!0},$done:{configurable:!0}};return e.prototype.logger=function(){},r.$name.get=function(){return"to1source-event"},r.is.get=function(){return this.$name},e.prototype.$on=function(t,e,r){var n=this;void 0===r&&(r=null);this.validate(t,e);var o=this.takeFromStore(t);if(!1===o)return this.logger('($on) "'+t+'" is not in lazy store'),this.addToNormalStore(t,"on",e,r);this.logger("($on) "+t+" found in lazy store");var i=0;return o.forEach((function(o){var a=o[0],u=o[1],c=o[2];if(c&&"on"!==c)throw new Error(An+" "+c);n.logger("($on)",'call run "'+t+'"'),n.run(e,a,r||u),i+=n.addToNormalStore(t,"on",e,r||u)})),this.logger("($on) return size "+i),i},e.prototype.$once=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=this.takeFromStore(t);this.normalStore;if(!1===n)return this.logger('($once) "'+t+'" is not in the lazy store'),this.addToNormalStore(t,"once",e,r);this.logger("($once)",n);var o=Array.from(n)[0],i=o[0],a=o[1],u=o[2];if(u&&"once"!==u)throw new Error(An+" "+u);this.logger("($once)",'call run "'+t+'"'),this.run(e,i,r||a),this.$off(t)},e.prototype.$only=function(t,e,r){var n=this;void 0===r&&(r=null),this.validate(t,e);var o=!1,i=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger('($only) "'+t+'" add to normalStore'),o=this.addToNormalStore(t,"only",e,r)),!1!==i)&&(this.logger('($only) "'+t+'" found data in lazy store to execute'),Array.from(i).forEach((function(o){var i=o[0],a=o[1],u=o[2];if(u&&"only"!==u)throw new Error(An+" "+u);n.logger('($only) call run "'+t+'"'),n.run(e,i,r||a)})));return o},e.prototype.$onlyOnce=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=!1,o=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger('($onlyOnce) "'+t+'" add to normalStore'),n=this.addToNormalStore(t,"onlyOnce",e,r)),!1!==o){this.logger("($onlyOnce)",o);var i=Array.from(o)[0],a=i[0],u=i[1],c=i[2];if(c&&"onlyOnce"!==c)throw new Error(An+" "+c);this.logger('($onlyOnce) call run "'+t+'"'),this.run(e,a,r||u),this.$off(t)}return n},e.prototype.$replace=function(t,e,r,n){if(void 0===r&&(r=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,e),Reflect.apply(o,this,[t,e,r])}throw new Error(n+" is not supported!")},e.prototype.$trigger=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,i=this.normalStore;if(this.logger("($trigger) normalStore",i),i.has(t)){if(this.logger('($trigger) "'+t+'" found'),this.$queue(t,e,r,n))return this.logger('($trigger) Currently suspended "'+t+'" added to queue, nothing executed. Exit now.'),!1;for(var a=Array.from(i.get(t)),u=a.length,c=!1,s=0;s0;)n[o]=arguments[o+2];if(t.has(e)?(this.logger('(addToStore) "'+e+'" existed'),r=t.get(e)):(this.logger('(addToStore) create new Set for "'+e+'"'),r=new Set),n.length>2)if(Array.isArray(n[0])){var i=n[2];this.checkTypeInLazyStore(e,i)||r.add(n)}else this.checkContentExist(n,r)||(this.logger("(addToStore) insert new",n),r.add(n));else r.add(n);return t.set(e,r),[t,r.size]},e.prototype.checkContentExist=function(t,e){return!!Array.from(e).filter((function(e){return e[0]===t[0]})).length},e.prototype.checkTypeInStore=function(t,e){this.validateEvt(t,e);var r=this.$get(t,!0);return!1===r||!r.filter((function(t){var r=t[3];return e!==r})).length},e.prototype.checkTypeInLazyStore=function(t,e){this.validateEvt(t,e);var r=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",r),!!r&&!!Array.from(r).filter((function(t){return t[2]!==e})).length},e.prototype.addToNormalStore=function(t,e,r,n){if(void 0===n&&(n=null),this.logger('(addToNormalStore) try to add "'+e+'" --\x3e "'+t+'" to normal store'),this.checkTypeInStore(t,e)){this.logger("(addToNormalStore)",'"'+e+'" --\x3e "'+t+'" can add to normal store');var o=this.hashFnToKey(r),i=[this.normalStore,t,o,r,n,e],a=Reflect.apply(this.addToStore,this,i),u=a[0],c=a[1];return this.normalStore=u,c}return!1},e.prototype.addToLazyStore=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(e),r];n&&o.push(n);var i=Reflect.apply(this.addToStore,this,o),a=i[0],u=i[1];return this.lazyStore=a,this.logger("(addToLazyStore) size: "+u),u},e.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},r.normalStore.set=function(t){Tn.set(this,t)},r.normalStore.get=function(){return Tn.get(this)},r.lazyStore.set=function(t){xn.set(this,t)},r.lazyStore.get=function(){return xn.get(this)},e.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,e){return(t=(t<<5)-t+e.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(e.prototype,r),e}(Nn))),qn=function(t){var e=t.toLowerCase();return e.indexOf("http")>-1?e.indexOf("https")>-1?e.replace("https","wss"):e.replace("http","ws"):e},Fn=function(t,e,r){return[Te(t,e.loginHandlerName,(function(t){if(t&&wn(t))return e.log("Received __login__ with "+t),r.$trigger("__login__",[t]);throw new Je(e.loginHandlerName,"Unexpected token "+t)})),e,r]},Mn=function(t,e,r){return[Te(t,e.logoutHandlerName,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__logout__",t)})),e,r]},Ln=function(t,e,r){return[Ae(t,"onLogin",(function(t){K(t)&&r.$only("onLogin",t)})),e,r]};function Jn(t,e,r){return X(Fn,Mn,Ln)(t,e,r)}function Wn(t,e,r){G(t,"error")?r(t.error):G(t,"data")?e(t.data):r({message:"UKNNOWN RESULT!",error:t})}function Un(t,e,r,n,o){void 0===n&&(n=[]);var i=V(e,"emit_reply");return o("actionCall: "+i+" --\x3e "+r,n),t.$trigger(i,[r,B(n)]),new Promise((function(n,i){var a=V(e,r,"onResult");t.$on(a,(function(t){o("got the first result",t),Wn(t,n,i)}))}))}var Dn,In,Bn,Hn=function(t,e,r,n,o,i){return Ae(t,"send",Q,(function(){return function(){for(var t=[],a=arguments.length;a--;)t[a]=arguments[a];return On(t,o.params,!0).then((function(t){return i(r,n,t),Un(e,r,n,t,_log)})).catch((function(t){i("send error",t),e.$call(V(r,n,"onError"),[new Je(n,t)])}))}}))},Gn=function(t,e,r,n,o,i){return[Te(t,"myNamespace",r),e,r,n,o,i]},Vn=function(t,e,r,n,o,i){return[Ae(t,"onResult",(function(t){K(t)&&e.$on(V(r,n,"onResult"),(function(o){Wn(o,t,(function(t){i('Catch error: "'+n+'"',t),e.$trigger(V(r,n,"onError"),t)}))}))})),e,r,n,o,i]},Yn=function(t,e,r,n,o,i){return[Ae(t,"onMessage",(function(t){if(K(t)){e.$only(V(r,n,"onMessage"),(function(o){Wn(o,t,(function(t){i('Catch error: "'+n+'"',t),e.$trigger(V(r,n,"onError"),t)}))}))}})),e,r,n,o,i]},Kn=function(t,e,r,n,o,i){return[Ae(t,"onError",(function(t){K(t)&&e.$only(V(r,n,"onError"),t)})),e,r,n,o,i]};function Qn(t,e,r,n,o,i){var a=[Gn,Vn,Yn,Kn,Hn],u=Reflect.apply(X,null,a),c=[n,o,t,e,r,i];return Reflect.apply(u,null,c)}function Xn(t,e,r,n,o){return function(){for(var i=[],a=arguments.length;a--;)i[a]=arguments[a];return On(i,n.params,!0).then((function(n){return Un(t,e,r,n,o)})).catch(De)}}function Zn(t,e,r){var n={},o=t.log;for(var i in r){var a=r[i];for(var u in a){var c=a[u];n=Te(n,u,Qn(i,u,c,Xn(e,i,u,c,o),e,o))}}return[n,t,e,r]}function to(t,e,r,n){return[Ae(t,"onError",(function(t){if(K(t))for(var e in n)r.$on(V(e,"onError"),t)})),e,r]}function eo(t,e,r){return[Ae(t,"onReady",(function(t){K(t)&&r.$only("onReady",t)})),e,r]}function ro(t,e,r){var n=function(t,e,r){return Te(t,e.disconnectHandlerName,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__disconnect__",t)}))}(t,e,r);return e.log("---\x3e The final step to return the ws-client <---"),n.verifyEventEmitter=function(){return r.is},n.eventEmitter=e.eventEmitter,n.log=e.log,n}var no=["roundtip","handshake"],oo={};oo.standalone=Sn(!1,["boolean"]),oo.debugOn=Sn(!1,["boolean"]),oo.loginHandlerName=Sn("login",["string"]),oo.logoutHandlerName=Sn("logout",["string"]),oo.disconnectHandlerName=Sn("disconnect",["string"]),oo.switchUserHandlerName=Sn("switch-user",["string"]),oo.hostname=Sn(!1,["string"]),oo.namespace=Sn("jsonql",["string"]),oo.wsOptions=Sn({},["object"]),oo.contract=Sn({},["object"],((Dn={}).checker=function(t){return!!function(t){return j(t)&&(G(t,"query")||G(t,"mutation")||G(t,"socket"))}(t)&&t},Dn)),oo.enableAuth=Sn(!1,["boolean"]),oo.token=Sn(!1,["string"]),oo.loginMethod=Sn("handshake",["string"],((In={}).enumv=no,In)),oo.useJwt=Sn(!0,["boolean","string"]),oo.authStrKey=Sn(null,["string"]);var io={};io.serverType=Sn(null,["string"],((Bn={}).alias="socketClientType",Bn));var ao=Object.assign(oo,io),uo={log:null,eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:"",publicNamespace:"public",privateNamespace:"private"};function co(t){return Promise.resolve(t).then((function(t){return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new Je(t)}}()),t.wssPath=qn([t.hostname,t.namespace].join("/"),t.serverType),t.log=$n(t),t.eventEmitter=function(t){var e=t.log,r=t.eventEmitter;return r?(e("eventEmitter is:",r.name),r):new Rn(t.log)}(t),t}))}function so(t){var e,r,n,o,i;return{opts:t,nspMap:(r=(e=t).contract,n=e.enableAuth,o=function(t){var e="jsonql";return t.enableAuth?[[e,t.privateNamespace].join("/"),[e,t.publicNamespace].join("/")]:[e]}(e),i=n?Ve(r):function(t,e){var r,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(r={},r[e]=n,r),publicNamespace:e}}(r.socket,o[0]),Object.assign(i,{namespaces:o})),ee:t.eventEmitter}}function fo(t){return function(e){return void 0===e&&(e={}),co(e).then(so).then((function(t){return function(t,e,r){var n=[Zn,eo,to];return t.enableAuth&&n.push(Jn),Reflect.apply(X,null,n)(t,r,e.nspGroup)}(t.opts,t.nspMap,t.ee)})).then((function(e){var r=e.opts,n=e.nspMap,o=e.ee;return t(r,n,o)})).then((function(t){return Reflect.apply(ro,null,t)})).catch((function(t){console.error("jsonql-ws-core-client init error",t)}))}}function lo(t,e,r){return void 0===e&&(e={}),void 0===r&&(r={}),function(n){return void 0===n&&(n={}),function(t,e,r){var n=Object.assign(ao,e),o=Object.assign(uo,r);return En(t,n,o)}(n,e,r).then(fo(t))}}function po(t,e){var r=e.hostname,n=e.wssPath,o=e.wsOptions,i=e.nspClient,a=e.log,u=t?[r,t].join("/"):n;return a("createNspClient --\x3e ",u),i(u,o)}var ho=function(t,e,r,n){var o=n.log;r.$on("__logout__",(function(){var i=getPrivateNamespace(e);o("__logout__ event triggered"),function(t,e,r){e.forEach((function(e){t.$trigger(V(e,"onError"),[{message:r,namespace:e}])}))}(r,[i],"__logout__"),o("logout from "+i),function(t,e){B(e).forEach((function(e){t.$off(V(e,"emit_reply"))}))}(r,i),t[i]=null,notLoginWsListerner(i,r,n)}))};function vo(t,e){return function(r,n,o){var i=r.log,a=n.namespaces,u=function(t){return t.length>1&&t[0]}(a);return a.map((function(n){var c=u===n;if(i(n," --\x3e "+(c?"private":"public")+" nsp --\x3e ",!1!==e[n]),e[n]){i("[call bindWsHandler]",c,n);var s=[n,e[n],o,c,r];Reflect.apply(t,null,s)}else i("binding notLoginWsHandler to "+n),function(t,e,r){var n=r.log;e.$only(V(t,"emit_reply"),(function(r,o){n("[notLoginListerner] hijack the ws call",t,r,o);var i={message:"NOT LOGIN"};e.$call(V(t,r,"onError"),[i]),e.$call(V(t,r,"onResult"),[{error:i}])}))}(n,o,r);return c&&(i("Has private and add logoutEvtHandler"),ho(e,a,o,r)),c}))}}var go={version:"version: 1.2.0 module: umd",serverType:"ws"},yo=null;"undefined"!=typeof WebSocket?yo=WebSocket:"undefined"!=typeof MozWebSocket?yo=MozWebSocket:void 0!==e?yo=e.WebSocket||e.MozWebSocket:"undefined"!=typeof window?yo=window.WebSocket||window.MozWebSocket:"undefined"!=typeof self&&(yo=self.WebSocket||self.MozWebSocket);var _o=yo;function bo(t,e,r,n,o,i){t.onopen=function(){t.send(Ge("__intercom__",["__ping__",Ie()]))},t.onmessage=function(a){try{var u=Qe(a.data);setTimeout((function(){t.terminate()}),50);var c=new e(r,Object.assign(i,u));n(c)}catch(t){o(t)}},t.onerror=function(t){o(t)}}function mo(t,e,r){return new Promise((function(n,o){bo(new t(e,r),t,e,n,o,r)}))}function jo(t,e,r){return!1===e?function(e,n){void 0===n&&(n={});var o=qn(e);return r("nspClient: \n"+o+"\n",n),mo(t,o,n)}:function(e,n,o){void 0===o&&(o={});var i=qn(e),a=n&&"string"==typeof n?i+"?token="+n:i;return r("nspAuthClient: \n"+a+"\n",o),mo(t,a,o)}}var wo=Array.isArray,Oo="object"==typeof e&&e&&e.Object===Object&&e,So="object"==typeof self&&self&&self.Object===Object&&self,Eo=Oo||So||Function("return this")(),ko=Eo.Symbol,$o=Object.prototype,Ao=$o.hasOwnProperty,To=$o.toString,xo=ko?ko.toStringTag:void 0;var Po=Object.prototype.toString;var zo=ko?ko.toStringTag:void 0;function No(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":zo&&zo in Object(t)?function(t){var e=Ao.call(t,xo),r=t[xo];try{t[xo]=void 0;var n=!0}catch(t){}var o=To.call(t);return n&&(e?t[xo]=r:delete t[xo]),o}(t):function(t){return Po.call(t)}(t)}var Co=function(t,e){return function(r){return t(e(r))}}(Object.getPrototypeOf,Object);function Ro(t){return null!=t&&"object"==typeof t}var qo=Function.prototype,Fo=Object.prototype,Mo=qo.toString,Lo=Fo.hasOwnProperty,Jo=Mo.call(Object);function Wo(t){if(!Ro(t)||"[object Object]"!=No(t))return!1;var e=Co(t);if(null===e)return!0;var r=Lo.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&Mo.call(r)==Jo}var Uo=function(t,e){void 0===e&&(e=!0);try{return JSON.parse(t)}catch(r){if(e)return t;throw new Error(r)}},Do=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return t.join("_")},Io=function(t){return Uo("string"==typeof t?t:JSON.stringify(t))},Bo=function(){return!1};function Ho(t,e){return t===e||t!=t&&e!=e}function Go(t,e){for(var r=t.length;r--;)if(Ho(t[r][0],e))return r;return-1}var Vo=Array.prototype.splice;function Yo(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1},Yo.prototype.set=function(t,e){var r=this.__data__,n=Go(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};function Qo(t){if(!Ko(t))return!1;var e=No(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}var Xo=Eo["__core-js_shared__"],Zo=function(){var t=/[^.]+$/.exec(Xo&&Xo.keys&&Xo.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}();var ti=Function.prototype.toString;var ei=/^\[object .+?Constructor\]$/,ri=Function.prototype,ni=Object.prototype,oi=ri.toString,ii=ni.hasOwnProperty,ai=RegExp("^"+oi.call(ii).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function ui(t){return!(!Ko(t)||function(t){return!!Zo&&Zo in t}(t))&&(Qo(t)?ai:ei).test(function(t){if(null!=t){try{return ti.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function ci(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return ui(r)?r:void 0}var si=ci(Eo,"Map"),fi=ci(Object,"create");var li=Object.prototype.hasOwnProperty;var pi=Object.prototype.hasOwnProperty;function hi(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&t<=9007199254740991}function Fi(t){return null!=t&&qi(t.length)&&!Qo(t)}var Mi="object"==typeof exports&&exports&&!exports.nodeType&&exports,Li=Mi&&"object"==typeof module&&module&&!module.nodeType&&module,Ji=Li&&Li.exports===Mi?Eo.Buffer:void 0,Wi=(Ji?Ji.isBuffer:void 0)||function(){return!1},Ui={};Ui["[object Float32Array]"]=Ui["[object Float64Array]"]=Ui["[object Int8Array]"]=Ui["[object Int16Array]"]=Ui["[object Int32Array]"]=Ui["[object Uint8Array]"]=Ui["[object Uint8ClampedArray]"]=Ui["[object Uint16Array]"]=Ui["[object Uint32Array]"]=!0,Ui["[object Arguments]"]=Ui["[object Array]"]=Ui["[object ArrayBuffer]"]=Ui["[object Boolean]"]=Ui["[object DataView]"]=Ui["[object Date]"]=Ui["[object Error]"]=Ui["[object Function]"]=Ui["[object Map]"]=Ui["[object Number]"]=Ui["[object Object]"]=Ui["[object RegExp]"]=Ui["[object Set]"]=Ui["[object String]"]=Ui["[object WeakMap]"]=!1;var Di="object"==typeof exports&&exports&&!exports.nodeType&&exports,Ii=Di&&"object"==typeof module&&module&&!module.nodeType&&module,Bi=Ii&&Ii.exports===Di&&Oo.process,Hi=function(){try{var t=Ii&&Ii.require&&Ii.require("util").types;return t||Bi&&Bi.binding&&Bi.binding("util")}catch(t){}}(),Gi=Hi&&Hi.isTypedArray,Vi=Gi?function(t){return function(e){return t(e)}}(Gi):function(t){return Ro(t)&&qi(t.length)&&!!Ui[No(t)]};function Yi(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var Ki=Object.prototype.hasOwnProperty;function Qi(t,e,r){var n=t[e];Ki.call(t,e)&&Ho(n,r)&&(void 0!==r||e in t)||_i(t,e,r)}var Xi=/^(?:0|[1-9]\d*)$/;function Zi(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&Xi.test(t))&&t>-1&&t%1==0&&t0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(la);function va(t,e){return ha(function(t,e,r){return e=fa(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,i=fa(n.length-e,0),a=Array(i);++o1?r[o-1]:void 0,a=o>2?r[2]:void 0;for(i=t.length>3&&"function"==typeof i?(o--,i):void 0,a&&function(t,e,r){if(!Ko(r))return!1;var n=typeof e;return!!("number"==n?Fi(r)&&Zi(e,r.length):"string"==n&&e in r)&&Ho(r[e],t)}(r[0],r[1],a)&&(i=o<3?void 0:i,o=1),e=Object(e);++n0;)e[r]=arguments[r+1];var n=Ie(),o=[t].concat(e);return o.push(n),Ge("__intercom__",o)}("__logout__")),log("terminate ws connection"),e.terminate()}catch(t){console.error("ws.terminate error",t)}}))};function Ea(t,e,r,n,o){var i=o.log,a=2;e.onopen=function(){i("=== ws.onopen listened --\x3e",t),r.$call("onReady")(t),0===--a&&r.$off("onReady"),n&&(i("isPrivate and fire the onLogin"),r.$call("onLogin")(t)),r.$only(Do(t,"emit_reply"),(function(t,r){var n=function(t,e,r){return void 0===e&&(e=[]),void 0===r&&(r=!1),JSON.stringify(ma(t,e,r))}(t,r);i("ws.onopen.send",t,r,n),e.send(n)}))},e.onmessage=function(e){try{var n=function(t,e){void 0===e&&(e=Bo);try{var r,n=Io(t);if(!1!==(r=wa(n)))return e("TS",n.TS),{data:Io(r.__data__),resolverName:r.__event__,type:r.__reply__};throw new ya("payload can not decoded",t)}catch(t){return e("error",t)}}(e.data),o=n.resolverName,a=n.type;switch(i("Respond from server",a,n),a){case"emit_reply":var u=Do(t,o,"onMessage"),c=r.$trigger(u,[n]);i("EMIT_REPLY_TYPE",u,c);break;case"acknowledge_reply":var s=Do(t,o,"onResult"),f=r.$trigger(s,[n]);i("ACKNOWLEDGE_REPLY_TYPE",s,f);break;case"error":i("ERROR_KEY"),Oa(r,t,o,n);break;default:i("Unhandled event!",n),Oa(r,t,o,n)}}catch(e){console.error("ws.onmessage error",e),Oa(r,t,!1,e)}},e.onclose=function(){i("ws.onclose callback")},e.onerror=function(e){i("ws.onerror",e),function(t,e,r){t.$trigger(V(e,"onError"),[r])}(r,t,e)},n&&Sa(r,e)}var ka=function(t,e,r){var n,o,i=t.log,a=e.publicNamespace,u=e.namespaces;return i("createNspAction","publicNamespace",a,"namespaces",u),t.enableAuth?(n=u.map((function(e,n){return 0===n?r?(t.token=r,i("create createNspAuthClient at run time"),function(t,e){var r=e.hostname,n=e.wssPath,o=e.token,i=e.wsOptions,a=e.nspAuthClient,u=e.log,c=t?[r,t].join("/"):n;if(u("createNspAuthClient --\x3e",c),o&&"string"!=typeof o)throw new Error("Expect token to be string, but got "+o);return a(c,o,i)}(e,t)):Promise.resolve(!1):po(e,t)})),void 0===o&&(o=!1),n.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===o?t.concat([e]):da(t,e)}))}))}),Promise.resolve(!1===o?[]:Wo(o)?o:{}))).then((function(t){return t.map((function(t,e){var r;return(r={})[u[e]]=t,r})).reduce((function(t,e){return Object.assign(t,e)}),{})})):po(!1,t).then((function(t){var e;return(e={})[a]=t,e}))};var $a,Aa=($a=_o,function(t,e,r){var n=t.log;return t.nspClient=jo($a,!1,n),t.nspAuthClient=jo($a,!0,n),n("bindFrameworkToJsonql",r.name,e),function(t,e,r){var n=t.token;return ka(t,e,n).then((function(n){return vo(Ea,n)(t,e,r),t.enableAuth&&loginEventHandler(t,e,r),{opts:t,nspMap:e,ee:r}}))}(t,e,r)});return function(t,e){return void 0===t&&(t={}),void 0===e&&(e={}),lo(Aa,{},Object.assign({},go,e))(t)}}));
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).jsonqlWsClient=e()}(this,(function(){"use strict";var t=Array.isArray,e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},r="object"==typeof e&&e&&e.Object===Object&&e,n="object"==typeof self&&self&&self.Object===Object&&self,o=r||n||Function("return this")(),i=o.Symbol,a=Object.prototype,u=a.hasOwnProperty,c=a.toString,s=i?i.toStringTag:void 0;var f=Object.prototype.toString;var l=i?i.toStringTag:void 0;function p(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":l&&l in Object(t)?function(t){var e=u.call(t,s),r=t[s];try{t[s]=void 0;var n=!0}catch(t){}var o=c.call(t);return n&&(e?t[s]=r:delete t[s]),o}(t):function(t){return f.call(t)}(t)}function h(t,e){return function(r){return t(e(r))}}var v=h(Object.getPrototypeOf,Object);function g(t){return null!=t&&"object"==typeof t}var d=Function.prototype,y=Object.prototype,_=d.toString,b=y.hasOwnProperty,m=_.call(Object);function j(t){if(!g(t)||"[object Object]"!=p(t))return!1;var e=v(t);if(null===e)return!0;var r=b.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&_.call(r)==m}function w(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var i=Array(o);++n-1;);return r}(n,o),function(t,e){for(var r=t.length;r--&&A(e,t[r],0)>-1;);return r}(n,o)+1).join("")}var B=function(e){return t(e)?e:[e]},V=function(t,e){void 0===e&&(e=!0);try{return JSON.parse(t)}catch(r){if(e)return t;throw new Error(r)}},G=function(t,e){try{var r=Object.keys(t);return n=e,!!r.filter((function(t){return t===n})).length}catch(t){return!1}var n},H=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return t.join("_")},K=function(t){return V("string"==typeof t?t:JSON.stringify(t))},Y=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},Q=function(){return!1},X=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return Reflect.apply(e,null,B(t))}),Reflect.apply(t,null,r))}};function Z(t,e){return t===e||t!=t&&e!=e}function tt(t,e){for(var r=t.length;r--;)if(Z(t[r][0],e))return r;return-1}var et=Array.prototype.splice;function rt(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1},rt.prototype.set=function(t,e){var r=this.__data__,n=tt(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};function ot(t){if(!nt(t))return!1;var e=p(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}var it,at=o["__core-js_shared__"],ut=(it=/[^.]+$/.exec(at&&at.keys&&at.keys.IE_PROTO||""))?"Symbol(src)_1."+it:"";var ct=Function.prototype.toString;function st(t){if(null!=t){try{return ct.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var ft=/^\[object .+?Constructor\]$/,lt=Function.prototype,pt=Object.prototype,ht=lt.toString,vt=pt.hasOwnProperty,gt=RegExp("^"+ht.call(vt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function dt(t){return!(!nt(t)||(e=t,ut&&ut in e))&&(ot(t)?gt:ft).test(st(t));var e}function yt(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return dt(r)?r:void 0}var _t=yt(o,"Map"),bt=yt(Object,"create");var mt=Object.prototype.hasOwnProperty;var jt=Object.prototype.hasOwnProperty;function wt(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&t<=9007199254740991}function Gt(t){return null!=t&&Vt(t.length)&&!ot(t)}var Ht="object"==typeof exports&&exports&&!exports.nodeType&&exports,Kt=Ht&&"object"==typeof module&&module&&!module.nodeType&&module,Yt=Kt&&Kt.exports===Ht?o.Buffer:void 0,Qt=(Yt?Yt.isBuffer:void 0)||function(){return!1},Xt={};Xt["[object Float32Array]"]=Xt["[object Float64Array]"]=Xt["[object Int8Array]"]=Xt["[object Int16Array]"]=Xt["[object Int32Array]"]=Xt["[object Uint8Array]"]=Xt["[object Uint8ClampedArray]"]=Xt["[object Uint16Array]"]=Xt["[object Uint32Array]"]=!0,Xt["[object Arguments]"]=Xt["[object Array]"]=Xt["[object ArrayBuffer]"]=Xt["[object Boolean]"]=Xt["[object DataView]"]=Xt["[object Date]"]=Xt["[object Error]"]=Xt["[object Function]"]=Xt["[object Map]"]=Xt["[object Number]"]=Xt["[object Object]"]=Xt["[object RegExp]"]=Xt["[object Set]"]=Xt["[object String]"]=Xt["[object WeakMap]"]=!1;var Zt,te="object"==typeof exports&&exports&&!exports.nodeType&&exports,ee=te&&"object"==typeof module&&module&&!module.nodeType&&module,re=ee&&ee.exports===te&&r.process,ne=function(){try{var t=ee&&ee.require&&ee.require("util").types;return t||re&&re.binding&&re.binding("util")}catch(t){}}(),oe=ne&&ne.isTypedArray,ie=oe?(Zt=oe,function(t){return Zt(t)}):function(t){return g(t)&&Vt(t.length)&&!!Xt[p(t)]};function ae(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var ue=Object.prototype.hasOwnProperty;function ce(t,e,r){var n=t[e];ue.call(t,e)&&Z(n,r)&&(void 0!==r||e in t)||kt(t,e,r)}var se=/^(?:0|[1-9]\d*)$/;function fe(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&se.test(t))&&t>-1&&t%1==0&&t0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(we);function Ee(t,e){return Se(function(t,e,r){return e=je(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,i=je(n.length-e,0),a=Array(i);++o1?e[n-1]:void 0,i=n>2?e[2]:void 0;for(o=$e.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,e,r){if(!nt(r))return!1;var n=typeof e;return!!("number"==n?Gt(r)&&fe(e,r.length):"string"==n&&e in r)&&Z(r[e],t)}(e[0],e[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++r0))},ar=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var e=t.replace("array.<","").replace(">","");return e.indexOf("|")?e.split("|"):[e]}return!1},ur=function(t,e){var r=t.arg;return e.length>1?!r.filter((function(t){return!(e.length>e.filter((function(e){return!or(e)(t)})).length)})).length:e.length>e.filter((function(t){return!ir(r,t)})).length},cr=function(t,e){if(void 0===e&&(e=null),j(t)){if(!e)return!0;if(ir(e))return!e.filter((function(e){var r=t[e.name];return!(e.type.length>e.type.filter((function(t){var e;return void 0===r||(!1!==(e=ar(t))?!ur({arg:r},e):!or(t)(r))})).length)})).length}return!1},sr=function(t,e){var r,n,o,i,a;switch(!0){case"object"===t:return o=(n=e).arg,i=n.param,a=[o],Array.isArray(i.keys)&&i.keys.length&&a.push(i.keys),!Reflect.apply(cr,null,a);case"array"===t:return!ir(e.arg);case!1!==(r=ar(t)):return!ur(e,r);default:return!or(t)(e.arg)}},fr=function(t,e){return void 0!==t?t:!0===e.optional&&void 0!==e.defaultvalue?e.defaultvalue:null},lr=function(t,e,r){var n;void 0===r&&(r=!1);var o=function(t,e){if(!ir(e))throw new We("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===e.length)return[];if(!ir(t))throw console.info(t),new We("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==e.length:return t.map((function(t,r){return{arg:t,index:r,param:e[r]}}));case!0===e[0].variable:var r=e[0].type;return t.map((function(t,n){return{arg:t,index:n,param:e[n]||{type:r,name:"_"}}}));case t.lengthe.length:var n=e.length,o=["any"];return t.map((function(t,r){var i=r>=n||!!e[r].optional,a=e[r]||{type:o,name:"_"+r};return{arg:i?fr(t,a):t,index:r,param:a,optional:i}}));default:throw new De("Could not understand your arguments and parameter structure!",{args:t,params:e})}}(t,e),i=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var e=t.arg,r=t.param;return!!Xe(e)&&!(r.type.length>r.type.filter((function(e){return sr(e,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(e){return sr(e,t)})).length)}));return r?((n={}).error=i,n.data=o.map((function(t){return t.arg})),n):i},pr=h(Object.keys,Object),hr=Object.prototype.hasOwnProperty;function vr(t){return Gt(t)?pe(t):function(t){if(!Wt(t))return pr(t);var e=[];for(var r in Object(t))hr.call(t,r)&&"constructor"!=r&&e.push(r);return e}(t)}function gr(t,e){return t&&Nt(t,e,vr)}function dr(t){var e=-1,r=null==t?0:t.length;for(this.__data__=new St;++eu))return!1;var s=i.get(t);if(s&&i.get(e))return s==e;var f=-1,l=!0,p=2&r?new dr:void 0;for(i.set(t,e),i.set(e,t);++f0){if(!1!==this.$get(t,!0)){var n=this.searchMapEvt(t);if(n.length){var o=n[0][3],i=(this.checkMaxStore(t,e),this);return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];var a=i.getMaxStore(t),u=-1;if(a>0){var c=i.$call(t,o,r);if(Reflect.apply(c,i,e),-1===(u=i.checkMaxStore(t)))return i.$off(t),-1}return u}}}return this.logger("The "+t+" is not registered, can not execute non-existing event at the moment"),-1}throw new Error("Expect max to be an integer and greater than zero! But we got ["+typeof e+"]"+e+" instead")},e.prototype.$replace=function(t,e,r,n){if(void 0===r&&(r=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,e),Reflect.apply(o,this,[t,e,r])}throw new Error(n+" is not supported!")},e.prototype.$trigger=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,i=this.normalStore;if(this.logger("($trigger) normalStore",i),i.has(t)){if(this.logger('($trigger) "'+t+'" found'),this.$queue(t,e,r,n))return this.logger('($trigger) Currently suspended "'+t+'" added to queue, nothing executed. Exit now.'),!1;for(var a=Array.from(i.get(t)),u=a.length,c=!1,s=0;s0&&--r,!(r>0))return this.maxCountStore.delete(t),this.logger("remove "+t+" from maxStore"),-1;this.maxCountStore.set(t,r)}return r}throw new Error("Expect max to be an integer, but we got "+typeof e+" "+e)},e.prototype.searchMapEvt=function(t){var e=this.$get(t,!0).filter((function(t){var e,r=t[3];return e=r,!!Nn.filter((function(t){return e===t})).length}));return e.length?e:[]},e.prototype.takeFromStore=function(t,e){void 0===e&&(e="lazyStore");var r=this[e];if(r){if(this.logger("(takeFromStore)",e,r),r.has(t)){var n=r.get(t);return this.logger('(takeFromStore) has "'+t+'"',n),r.delete(t),n}return!1}throw new Error('"'+e+'" is not supported!')},e.prototype.findFromStore=function(t,e,r){return void 0===r&&(r=!1),!!e.has(t)&&Array.from(e.get(t)).map((function(t){return r?t:t[1]}))},e.prototype.removeFromStore=function(t,e){return!!e.has(t)&&(this.logger("($off)",t),e.delete(t),!0)},e.prototype.getStoreSet=function(t,e){var r;return t.has(e)?(this.logger('(addToStore) "'+e+'" existed'),r=t.get(e)):(this.logger('(addToStore) create new Set for "'+e+'"'),r=new Set),r},e.prototype.addToStore=function(t,e){for(var r=[],n=arguments.length-2;n-- >0;)r[n]=arguments[n+2];var o=this.getStoreSet(t,e);if(r.length>2)if(Array.isArray(r[0])){var i=r[2];this.checkTypeInLazyStore(e,i)||o.add(r)}else this.checkContentExist(r,o)||(this.logger("(addToStore) insert new",r),o.add(r));else o.add(r);return t.set(e,o),[t,o.size]},e.prototype.checkContentExist=function(t,e){return!!Array.from(e).filter((function(e){return e[0]===t[0]})).length},e.prototype.checkTypeInStore=function(t,e){this.validateEvt(t,e);var r=this.$get(t,!0);return!1===r||!r.filter((function(t){var r=t[3];return e!==r})).length},e.prototype.checkTypeInLazyStore=function(t,e){this.validateEvt(t,e);var r=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",r),!!r&&!!Array.from(r).filter((function(t){return t[2]!==e})).length},e.prototype.addToNormalStore=function(t,e,r,n){if(void 0===n&&(n=null),this.logger('(addToNormalStore) try to add "'+e+'" --\x3e "'+t+'" to normal store'),this.checkTypeInStore(t,e)){this.logger("(addToNormalStore)",'"'+e+'" --\x3e "'+t+'" can add to normal store');var o=this.hashFnToKey(r),i=[this.normalStore,t,o,r,n,e],a=Reflect.apply(this.addToStore,this,i),u=a[0],c=a[1];return this.normalStore=u,c}return!1},e.prototype.addToLazyStore=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(e),r];n&&o.push(n);var i=Reflect.apply(this.addToStore,this,o),a=i[0],u=i[1];return this.lazyStore=a,this.logger("(addToLazyStore) size: "+u),u},e.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},r.normalStore.set=function(t){Cn.set(this,t)},r.normalStore.get=function(){return Cn.get(this)},r.lazyStore.set=function(t){Rn.set(this,t)},r.lazyStore.get=function(){return Rn.get(this)},Object.defineProperties(e.prototype,r),e}(function(t){function e(){t.call(this),this.__suspend_state__=null,this.__pattern__=null,this.queueStore=new Set}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={$queues:{configurable:!0}};return e.prototype.$suspend=function(){this.logger("---\x3e SUSPEND ALL OPS <---"),this.__suspend__(!0)},e.prototype.$release=function(){this.logger("---\x3e RELEASE SUSPENDED QUEUE <---"),this.__suspend__(!1)},e.prototype.$suspendEvent=function(t){var e=function(t){switch(!0){case!0===Tn(t):return t;case!0===Pn(t):return new RegExp(t);default:return!1}}(t);if(Tn(e))return this.__pattern__=e,this.$suspend();throw new Error('We expect a pattern variable to be string or RegExp, but we got "'+typeof e+'" instead')},e.prototype.$queue=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];if(this.logger("($queue) get called"),!0===this.__suspend_state__){if(Tn(this.__pattern__)){var n=this.__pattern__.test(t);if(!n)return!1}this.logger("($queue) added to $queue",e),this.queueStore.add([t].concat(e))}return!!this.__suspend_state__},r.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},e.prototype.__suspend__=function(t){if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value! we got "+typeof t);var e=this.__suspend_state__;this.__suspend_state__=t,this.logger('($suspend) Change from "'+e+'" --\x3e "'+t+'"'),!0===e&&!1===t&&this.__release__()},e.prototype.__release__=function(){var t=this,e=this.queueStore.size,r=this.__pattern__;if(this.__pattern__=null,this.logger("(release) was called with "+e+(r?' for "'+r+'"':"")+" item"+(e>1?"s":"")),e>0){var n=Array.from(this.queueStore);this.queueStore.clear(),this.logger("(release queue)",n),n.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}return e},Object.defineProperties(e.prototype,r),e}(Mn)))),Ln=function(t){var e=t.toLowerCase();return e.indexOf("http")>-1?e.indexOf("https")>-1?e.replace("https","wss"):e.replace("http","ws"):e},Wn=function(t,e){B(e).forEach((function(e){t.$off(H(e,"emit_reply"))}))};function Dn(t,e,r){G(t,"error")?r(t.error):G(t,"data")?Reflect.apply(e,null,[].concat(t.data)):r({message:"UKNNOWN RESULT!",error:t})}function Jn(t,e,r,n,o){void 0===n&&(n=[]);var i=H(e,"emit_reply");return o("actionCall: "+i+" --\x3e "+r,n),t.$trigger(i,[r,B(n)]),new Promise((function(n,i){var a=H(e,r,"onResult");t.$on(a,(function(t){o("got the first result",t),Dn(t,n,i)}))}))}var Un=function(t,e,r,n,o,i){return xe(t,"send",Q,(function(){return i("running call getter method"),function(){for(var t=[],a=arguments.length;a--;)t[a]=arguments[a];return On(t,o.params,!0).then((function(t){return i("execute send",r,n,t),Jn(e,r,n,t,i)})).catch((function(t){i("send error",t),e.$call(H(r,n,"onError"),[new We(n,t)])}))}}))};function In(t,e,r,n,o){return function(){for(var i=[],a=arguments.length;a--;)i[a]=arguments[a];return On(i,n.params,!0).then((function(n){return Jn(t,e,r,n,o)})).catch(Ue)}}var Bn=function(t,e,r,n,o,i){return[Ae(t,"myNamespace",r),e,r,n,o,i]},Vn=function(t,e,r,n,o,i){return[xe(t,"onResult",(function(t){Y(t)&&e.$on(H(r,n,"onResult"),(function(o){Dn(o,t,(function(t){i('Catch error: "'+n+'"',t),e.$trigger(H(r,n,"onError"),t)}))}))})),e,r,n,o,i]},Gn=function(t,e,r,n,o,i){return[xe(t,"onMessage",(function(t){if(Y(t)){e.$only(H(r,n,"onMessage"),(function(o){i("onMessageCallback",o),Dn(o,t,(function(t){i('Catch error: "'+n+'"',t),e.$trigger(H(r,n,"onError"),t)}))}))}})),e,r,n,o,i]},Hn=function(t,e,r,n,o,i){return[xe(t,"onError",(function(t){Y(t)&&e.$only(H(r,n,"onError"),t)})),e,r,n,o,i]};function Kn(t,e,r,n,o,i){var a=[Bn,Vn,Gn,Hn,Un];return Reflect.apply(X,null,a)(n,o,t,e,r,i)}function Yn(t,e,r){var n=t.log,o={};for(var i in r){var a=r[i];for(var u in a){var c=a[u];o=Ae(o,u,Kn(i,u,c,In(e,i,u,c,n),e,n))}}return[o,t,e,r]}function Qn(t,e,r){return[xe(t,"onReady",(function(t){Y(t)&&r.$only("onReady",t)})),e,r]}function Xn(t,e,r,n){return[xe(t,"onError",(function(t){if(Y(t))for(var e in n)r.$on(H(e,"onError"),t)})),e,r]}var Zn,to,eo,ro=function(t,e,r){return[Ae(t,e.loginHandlerName,(function(t){if(t&&wn(t))return e.log("Received __login__ with "+t),r.$trigger("__login__",[t]);throw new We(e.loginHandlerName,"Unexpected token "+t)})),e,r]},no=function(t,e,r){return[Ae(t,e.logoutHandlerName,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__logout__",t)})),e,r]},oo=function(t,e,r){return[xe(t,"onLogin",(function(t){Y(t)&&r.$only("onLogin",t)})),e,r]};function io(t,e,r){return X(ro,no,oo)(t,e,r)}function ao(t,e,r){return(0,e.log)("[1] setupConnectPropKey"),[t=Ae(t,"connected",!1,!0),e,r]}function uo(t,e,r){var n=e.log;return n("[2] setupConnectEvtListener"),r.$on("__connect__",(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];n("setupConnectEvtListener pass and do nothing at the moment",t)})),[t,e,r]}function co(t,e,r){var n=e.log;return n("[3] setupConnectedEvtListener"),r.$on("__connected__",(function(){var e;t.connected=!0;var o=r.$release();return n("CONNECTED_EVENT_NAME",!0,"queue count",o),(e={}).connected=!0,e})),[t,e,r]}function so(t,e,r){var n=e.log;return n("[4] setupDisconnectListener"),r.$on("__disconnect__",(function(){var e;return t.connected=!1,n("CONNECTED_EVENT_NAME",!1),(e={}).connected=!1,e})),[t,e,r]}function fo(t,e,r){var n=e.disconnectHandlerName;return(0,e.log)("[5] setupDisconectAction"),Ae(t,n,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__disconnect__",t)}))}function lo(t,e,r){var n=function(t,e,r){var n=[ao,uo,co,so,fo];return Reflect.apply(X,null,n)(t,e,r)}(t,e,r);return n.verifyEventEmitter=function(){return r.is},n.eventEmitter=e.eventEmitter,n.log=e.log,r.$trigger("__connect__",[e,r]),!0===e.suspendOnStart&&e.$releaseNamespace(),n}var po=["roundtip","handshake"],ho={};ho.standalone=Sn(!1,["boolean"]),ho.debugOn=Sn(!1,["boolean"]),ho.loginHandlerName=Sn("login",["string"]),ho.logoutHandlerName=Sn("logout",["string"]),ho.disconnectHandlerName=Sn("disconnect",["string"]),ho.switchUserHandlerName=Sn("switch-user",["string"]),ho.hostname=Sn(!1,["string"]),ho.namespace=Sn("jsonql",["string"]),ho.wsOptions=Sn({},["object"]),ho.contract=Sn({},["object"],((Zn={}).checker=function(t){return!!function(t){return j(t)&&(G(t,"query")||G(t,"mutation")||G(t,"socket"))}(t)&&t},Zn)),ho.enableAuth=Sn(!1,["boolean"]),ho.token=Sn(!1,["string"]),ho.loginMethod=Sn("handshake",["string"],((to={}).enumv=po,to)),ho.useJwt=Sn(!0,["boolean","string"]),ho.authStrKey=Sn(null,["string"]),ho.suspendOnStart=Sn(!1,["boolean"]);var vo={};vo.serverType=Sn(null,["string"],((eo={}).alias="socketClientType",eo));var go=Object.assign(ho,vo),yo={log:null,eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:"",publicNamespace:"public",privateNamespace:"private"};function _o(t){return Promise.resolve(t).then((function(t){return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new We(t)}}()),t.wssPath=Ln([t.hostname,t.namespace].join("/"),t.serverType),t.log=kn(t),t.eventEmitter=function(t){var e=t.log,r=t.eventEmitter;return r?(e("eventEmitter is:",r.name),r):new Fn(t.log)}(t),t}))}function bo(t){var e=function(t){var e=t.contract,r=t.enableAuth,n=function(t){var e="jsonql";return t.enableAuth?[[e,t.privateNamespace].join("/"),[e,t.publicNamespace].join("/")]:[e]}(t),o=r?He(e):function(t,e){var r,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(r={},r[e]=n,r),publicNamespace:e}}(e.socket,n[0]);return Object.assign(o,{namespaces:n})}(t),r=t.eventEmitter,n=t.log,o=e.namespaces;return n("namespaces",o),!0===t.suspendOnStart&&(t.$suspendNamepsace=function(){return o.forEach((function(t){return r.$suspendEvent(t)}))},t.$releaseNamespace=function(){return r.$release()},t.$suspendNamepsace()),{opts:t,nspMap:e,ee:r}}function mo(t){return function(e){return void 0===e&&(e={}),_o(e).then(bo).then((function(e){var r=e.opts,n=e.nspMap,o=e.ee;return t(r,n,o)})).then((function(t){return function(t,e,r){var n=[Yn,Qn,Xn];return t.enableAuth&&n.push(io),n.push(lo),Reflect.apply(X,null,n)(t,r,e.nspGroup)}(t.opts,t.nspMap,t.ee)})).catch((function(t){console.error("[jsonql-ws-core-client init error]",t)}))}}function jo(t,e,r){return void 0===e&&(e={}),void 0===r&&(r={}),function(n){return void 0===n&&(n={}),function(t,e,r){var n=Object.assign(go,e),o=Object.assign(yo,r);return En(t,n,o)}(n,e,r).then(mo(t))}}function wo(t,e){var r=e.hostname,n=e.wssPath,o=e.wsOptions,i=e.nspClient,a=e.log,u=t?[r,t].join("/"):n;return a("createNspClient --\x3e ",u),i(u,o)}var Oo=function(t,e,r,n){var o=n.log;r.$on("__logout__",(function(){var i=getPrivateNamespace(e);o("__logout__ event triggered"),function(t,e,r){e.forEach((function(e){t.$trigger(H(e,"onError"),[{message:r,namespace:e}])}))}(r,[i],"__logout__"),o("logout from "+i),Wn(r,i),t[i]=null,notLoginWsListerner(i,r,n)}))};function So(t,e){return function(r,n,o){var i=r.log,a=n.namespaces,u=function(t){return t.length>1&&t[0]}(a);return a.map((function(n){var c=u===n;if(i(n," --\x3e "+(c?"private":"public")+" nsp --\x3e ",!1!==e[n]),e[n]){i("[call bindWsHandler]",c,n);var s=[n,e[n],o,c,r];Reflect.apply(t,null,s)}else i("binding notLoginWsHandler to "+n),function(t,e,r){var n=r.log;e.$only(H(t,"emit_reply"),(function(r,o){n("[notLoginListerner] hijack the ws call",t,r,o);var i={message:"NOT LOGIN"};e.$call(H(t,r,"onError"),[i]),e.$call(H(t,r,"onResult"),[{error:i}])}))}(n,o,r);return c&&(i("Has private and add logoutEvtHandler"),Oo(e,a,o,r)),c}))}}var Eo={version:"version: 1.2.0 module: umd",serverType:"ws"},$o=null;"undefined"!=typeof WebSocket?$o=WebSocket:"undefined"!=typeof MozWebSocket?$o=MozWebSocket:void 0!==e?$o=e.WebSocket||e.MozWebSocket:"undefined"!=typeof window?$o=window.WebSocket||window.MozWebSocket:"undefined"!=typeof self&&($o=self.WebSocket||self.MozWebSocket);var ko=$o;function xo(t,e,r,n,o,i){return t.onopen=function(){t.send(Ge("__intercom__",["__ping__",Ie()]))},t.onmessage=function(a){try{var u=Qe(a.data);setTimeout((function(){t.terminate()}),50);var c=new e(r,Object.assign(i,u));n(c)}catch(t){o(t)}},t.onerror=function(t){o(t)},t}function Ao(t,e,r){return new Promise((function(n,o){return xo(new t(e,r),t,e,n,o,r)}))}function No(t,e,r){var n=r.log;return!1===e?function(e,r){void 0===r&&(r={});var o=Ln(e);return n("nspClient: \n"+o+"\n",r),Ao(t,o,r)}:function(e,r,o){void 0===o&&(o={});var i=Ln(e),a=r&&"string"==typeof r?i+"?token="+r:i;return n("nspAuthClient: \n"+a+"\n",o),Ao(t,a,o)}}var To="object"==typeof e&&e&&e.Object===Object&&e,Po="object"==typeof self&&self&&self.Object===Object&&self,zo=To||Po||Function("return this")(),Co=zo.Symbol,Ro=Object.prototype,Mo=Ro.hasOwnProperty,qo=Ro.toString,Fo=Co?Co.toStringTag:void 0;var Lo=Object.prototype.toString;var Wo=Co?Co.toStringTag:void 0;function Do(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":Wo&&Wo in Object(t)?function(t){var e=Mo.call(t,Fo),r=t[Fo];try{t[Fo]=void 0;var n=!0}catch(t){}var o=qo.call(t);return n&&(e?t[Fo]=r:delete t[Fo]),o}(t):function(t){return Lo.call(t)}(t)}var Jo=function(t,e){return function(r){return t(e(r))}}(Object.getPrototypeOf,Object);function Uo(t){return null!=t&&"object"==typeof t}var Io=Function.prototype,Bo=Object.prototype,Vo=Io.toString,Go=Bo.hasOwnProperty,Ho=Vo.call(Object);function Ko(t){if(!Uo(t)||"[object Object]"!=Do(t))return!1;var e=Jo(t);if(null===e)return!0;var r=Go.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&Vo.call(r)==Ho}function Yo(t,e){return t===e||t!=t&&e!=e}function Qo(t,e){for(var r=t.length;r--;)if(Yo(t[r][0],e))return r;return-1}var Xo=Array.prototype.splice;function Zo(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1},Zo.prototype.set=function(t,e){var r=this.__data__,n=Qo(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};function ei(t){if(!ti(t))return!1;var e=Do(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}var ri=zo["__core-js_shared__"],ni=function(){var t=/[^.]+$/.exec(ri&&ri.keys&&ri.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}();var oi=Function.prototype.toString;var ii=/^\[object .+?Constructor\]$/,ai=Function.prototype,ui=Object.prototype,ci=ai.toString,si=ui.hasOwnProperty,fi=RegExp("^"+ci.call(si).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function li(t){return!(!ti(t)||function(t){return!!ni&&ni in t}(t))&&(ei(t)?fi:ii).test(function(t){if(null!=t){try{return oi.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function pi(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return li(r)?r:void 0}var hi=pi(zo,"Map"),vi=pi(Object,"create");var gi=Object.prototype.hasOwnProperty;var di=Object.prototype.hasOwnProperty;function yi(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&t<=9007199254740991}function Ji(t){return null!=t&&Di(t.length)&&!ei(t)}var Ui="object"==typeof exports&&exports&&!exports.nodeType&&exports,Ii=Ui&&"object"==typeof module&&module&&!module.nodeType&&module,Bi=Ii&&Ii.exports===Ui?zo.Buffer:void 0,Vi=(Bi?Bi.isBuffer:void 0)||function(){return!1},Gi={};Gi["[object Float32Array]"]=Gi["[object Float64Array]"]=Gi["[object Int8Array]"]=Gi["[object Int16Array]"]=Gi["[object Int32Array]"]=Gi["[object Uint8Array]"]=Gi["[object Uint8ClampedArray]"]=Gi["[object Uint16Array]"]=Gi["[object Uint32Array]"]=!0,Gi["[object Arguments]"]=Gi["[object Array]"]=Gi["[object ArrayBuffer]"]=Gi["[object Boolean]"]=Gi["[object DataView]"]=Gi["[object Date]"]=Gi["[object Error]"]=Gi["[object Function]"]=Gi["[object Map]"]=Gi["[object Number]"]=Gi["[object Object]"]=Gi["[object RegExp]"]=Gi["[object Set]"]=Gi["[object String]"]=Gi["[object WeakMap]"]=!1;var Hi="object"==typeof exports&&exports&&!exports.nodeType&&exports,Ki=Hi&&"object"==typeof module&&module&&!module.nodeType&&module,Yi=Ki&&Ki.exports===Hi&&To.process,Qi=function(){try{var t=Ki&&Ki.require&&Ki.require("util").types;return t||Yi&&Yi.binding&&Yi.binding("util")}catch(t){}}(),Xi=Qi&&Qi.isTypedArray,Zi=Xi?function(t){return function(e){return t(e)}}(Xi):function(t){return Uo(t)&&Di(t.length)&&!!Gi[Do(t)]};function ta(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var ea=Object.prototype.hasOwnProperty;function ra(t,e,r){var n=t[e];ea.call(t,e)&&Yo(n,r)&&(void 0!==r||e in t)||wi(t,e,r)}var na=/^(?:0|[1-9]\d*)$/;function oa(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&na.test(t))&&t>-1&&t%1==0&&t0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(da);function ba(t,e){return _a(function(t,e,r){return e=ga(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,i=ga(n.length-e,0),a=Array(i);++o1?r[o-1]:void 0,a=o>2?r[2]:void 0;for(i=t.length>3&&"function"==typeof i?(o--,i):void 0,a&&function(t,e,r){if(!ti(r))return!1;var n=typeof e;return!!("number"==n?Ji(r)&&oa(e,r.length):"string"==n&&e in r)&&Yo(r[e],t)}(r[0],r[1],a)&&(i=o<3?void 0:i,o=1),e=Object(e);++n0;)e[r]=arguments[r+1];var n=Ie(),o=[t].concat(e);return o.push(n),Ge("__intercom__",o)}(LOGOUT_EVENT_NAME)),log("terminate ws connection"),e.terminate()}catch(t){console.error("ws.terminate error",t)}}))}var Ca=function(t,e,r,n){var o=[e];r&&o.push(r),o.push("onError");var i=Reflect.apply(Oa,null,o),a=n.data||n;t.$trigger(i,[a])};function Ra(t,e,r,n,o){var i=o.log,a=2;return n&&(i("Private namespace",t," binding to the DISCONNECT ws.terminate"),za(r,e)),e.onopen=function(){i("=== ws.onopen listened --\x3e",t),r.$trigger("onReady",[t]),0===--a&&r.$off("onReady"),n&&(i("isPrivate and fire the onLogin"),r.$call("onLogin")(t)),r.$only(Oa(t,"emit_reply"),(function(t,r){var n=function(t,e,r){return void 0===e&&(e=[]),void 0===r&&(r=!1),JSON.stringify(Na(t,e,r))}(t,r);i("ws.onopen.send",t,r,n),e.send(n)}))},e.onmessage=function(e){i("ws.onmessage raw payload",e.data);try{var n=function(t,e){void 0===e&&(e=Ea);try{var r,n=Sa(t);if(!1!==(r=Pa(n)))return e("_data",r),{data:Sa(r.__data__),resolverName:r.__event__,type:r.__reply__};throw new ka("payload can not decoded",t)}catch(t){return e("error",t)}}(e.data),o=n.resolverName,a=n.type;switch(i("Respond from server",a,n),a){case"emit_reply":var u=Oa(t,o,"onMessage"),c=r.$call(u)(n);i("EMIT_REPLY_TYPE",u,c);break;case"emit_acknowledge":var s=Oa(t,o,"onResult"),f=r.$call(s)(n);i("ACKNOWLEDGE_REPLY_TYPE",s,f);break;case"error":i("ERROR_KEY"),Ca(r,t,o,n);break;default:i("Unhandled event!",n),Ca(r,t,o,n)}}catch(e){i("ws.onmessage error",e),Ca(r,t,!1,e)}},e.onclose=function(){i("ws.onclose callback")},e.onerror=function(e){i("ws.onerror",e),function(t,e,r){t.$trigger(H(e,"onError"),[r])}(r,t,e)},e}var Ma,qa=(Ma=ko,function(t,e,r){var n=t.log;return n("There is problem here with passing the opts",t),t.nspClient=No(Ma,!1,t),t.nspAuthClient=No(Ma,!0,t),n("[1] bindWebsocketToJsonql",r.name,e),function(t,e,r){r("[2] setup the CONNECT_EVENT_NAME"),e.$only("__connect__",(function(e,n){return r("[3] CONNECT_EVENT_NAME",n),ja(e,t).then((function(t){return So(Ra,t)})).then((function(r){return r(e,t,n)}))}))}(e,r,n),function(t,e,r){var n=t.log,o=e.namespaces;n("[4] loginEventHandler"),r.$only("__login__",(function(e){n("createClient LOGIN_EVENT_NAME $only handler"),Wn(r,o),t.token=e,r.$trigger("__connect__",[t,r])}))}(t,e,r),n("just before returing the values for the next operation from createClientBindingAction"),{opts:t,nspMap:e,ee:r}});return function(t,e){return void 0===t&&(t={}),void 0===e&&(e={}),jo(qa,{},Object.assign({},Eo,e))(t)}}));
//# sourceMappingURL=jsonql-ws-client.umd.js.map
diff --git a/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js.map b/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js.map
index f20b0f8aa68a5bce88a3d2ede04b5be9cfedcd6b..3b57c88f9abfb6e6cb40a89df044e9c3166c78cd 100644
--- a/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js.map
+++ b/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js.map
@@ -1 +1 @@
-{"version":3,"file":"jsonql-ws-client.umd.js","sources":["../../../ws-client-core/node_modules/lodash-es/_arraySome.js"],"sourcesContent":["/**\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"],"names":["SetCache"],"mappings":"6qxBAAAA"}
\ No newline at end of file
+{"version":3,"file":"jsonql-ws-client.umd.js","sources":["../../../ws-client-core/node_modules/lodash-es/_arraySome.js"],"sourcesContent":["/**\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"],"names":["SetCache"],"mappings":"2vxBAAAA"}
\ No newline at end of file
diff --git a/packages/@jsonql/ws/main.js b/packages/@jsonql/ws/main.js
index ec55baa99da42e4c3489d98dca1b929cbab4697b..9b4087dc104a45ffce6f8576545e4989d765f5bc 100644
--- a/packages/@jsonql/ws/main.js
+++ b/packages/@jsonql/ws/main.js
@@ -35,6 +35,7 @@ var DISCONNECT_FN_NAME = 'disconnect';
var SWITCH_USER_FN_NAME = 'switch-user';
// headers
var CSRF_HEADER_KEY = 'X-CSRF-Token';
+
/* prop.js */
// this is all the key name for the config check map
@@ -67,7 +68,8 @@ var CONTRACT_PROP_KEY = 'contract';
var TOKEN_PROP_KEY = 'token';
var CONNECTED_PROP_KEY = 'connected';
-
/* socket.js */
+// track this key if we want to suspend event on start
+var SUSPEND_EVENT_PROP_KEY = 'suspendOnStart';
/* socket.js */
// the constants file is gettig too large
// we need to split up and group the related constant in one file
@@ -100,7 +102,7 @@ var WS_DATA_NAME = '__data__';
// for ws client, 1.9.3 breaking change to name them as FN instead of PROP
var ON_MESSAGE_FN_NAME = 'onMessage';
-var ON_RESULT_FN_NAME = 'onResult';
+var ON_RESULT_FN_NAME = 'onResult'; // this will need to be internal from now on
var ON_ERROR_FN_NAME = 'onError';
var ON_READY_FN_NAME = 'onReady';
var ON_LOGIN_FN_NAME = 'onLogin'; // new @1.8.6
@@ -3436,14 +3438,16 @@ var formatPayload = function (args) {
/**
* wrapper method to add the timestamp as well
- * @param {string} resolverName
- * @param {*} payload
+ * @param {string} resolverName name of the resolver
+ * @param {*} payload what is sending
+ * @param {object} extra additonal property we want to merge into the deliverable
* @return {object} delierable
*/
-function createDeliverable(resolverName, payload) {
+function createDeliverable(resolverName, payload, extra) {
var obj;
- return ( obj = {}, obj[resolverName] = payload, obj[TIMESTAMP_PARAM_NAME] = [ timestamp() ], obj )
+ if ( extra === void 0 ) extra = {};
+ return Object.assign(( obj = {}, obj[resolverName] = payload, obj[TIMESTAMP_PARAM_NAME] = [ timestamp() ], obj ), extra)
}
/**
@@ -3463,7 +3467,11 @@ function createQuery(resolverName, args, jsonp) {
}
return createDeliverable(resolverName, payload)
}
- throw new JsonqlValidationError("[createQuery] expect resolverName to be string and args to be array!", { resolverName: resolverName, args: args })
+ throw new JsonqlValidationError('utils:params-api:createQuery', {
+ message: "expect resolverName to be string and args to be array!",
+ resolverName: resolverName,
+ args: args
+ })
}
/**
@@ -3619,7 +3627,7 @@ var extractWsPayload = function (payload, cb) {
var _data;
if ((_data = isWsReply(json)) !== false) {
// note the ts property is on its own
- cb(TIMESTAMP_PARAM_NAME, json[TIMESTAMP_PARAM_NAME]);
+ cb('_data', _data);
return {
data: toJson(_data[WS_DATA_NAME]),
@@ -3770,7 +3778,7 @@ function isNumber(value) {
* _.isNaN(undefined);
* // => false
*/
-function isNaN(value) {
+function isNaN$1(value) {
// An `NaN` primitive is the only value that is not equal to itself.
// Perform the `toStringTag` check first to avoid errors with some
// ActiveX objects in IE.
@@ -3785,7 +3793,7 @@ function isNaN(value) {
* @return {boolean} true if OK
*/
var checkIsNumber = function(value) {
- return isString(value) ? false : !isNaN( parseFloat(value) )
+ return isString(value) ? false : !isNaN$1( parseFloat(value) )
};
// validate string type
@@ -4043,6 +4051,7 @@ var normalizeArgs = function(args, params) {
return []
}
if (!checkIsArray(args)) {
+ console.info(args);
throw new JsonqlValidationError(ARGS_NOT_ARRAY_ERR)
}
// debugFn(args, params);
@@ -6154,9 +6163,24 @@ var getLogFn = function (opts) {
var TAKEN_BY_OTHER_TYPE_ERR = 'You are trying to register an event already been taken by other type:';
-// Create two WeakMap store as a private keys
-var NB_EVENT_SERVICE_PRIVATE_STORE = new WeakMap();
-var NB_EVENT_SERVICE_PRIVATE_LAZY = new WeakMap();
+// use constants for type
+var ON_TYPE = 'on';
+var ONLY_TYPE = 'only';
+var ONCE_TYPE = 'once';
+var ONLY_ONCE_TYPE = 'onlyOnce';
+var NEG_RETURN = -1;
+
+var AVAILABLE_TYPES = [
+ ON_TYPE,
+ ONLY_TYPE,
+ ONCE_TYPE,
+ ONLY_ONCE_TYPE
+];
+// the type which the callMax can execute on
+var ON_MAX_TYPES = [
+ ON_TYPE,
+ ONLY_TYPE
+];
/**
* generate a 32bit hash based on the function.toString()
@@ -6195,6 +6219,18 @@ function isString$2(arg) {
return typeof arg === 'string'
}
+/**
+ * check if it's an integer
+ * @param {*} num input number
+ * @return {boolean}
+ */
+function isInt(num) {
+ if (isString$2(num)) {
+ throw new Error("Wrong type, we want number!")
+ }
+ return !isNaN(parseInt(num))
+}
+
/**
* Find from the array by matching the pattern
* @param {*} pattern a string or RegExp object
@@ -6211,133 +6247,253 @@ function getRegex(pattern) {
}
}
-// making all the functionality on it's own
-var SuspendClass = function SuspendClass() {
- // suspend, release and queue
- this.__suspend_state__ = null;
- // to do this proper we don't use a new prop to hold the event name pattern
- this.__pattern__ = null;
- this.queueStore = new Set();
-};
+/**
+ * in array
+ * @param {array} arr to search
+ * @param {*} prop to search
+ */
+ var inArray$2 = function (arr, prop) { return !!arr.filter(function (v) { return prop === v; }).length; };
-var prototypeAccessors = { $queues: { configurable: true } };
+// Create two WeakMap store as a private keys
+var NB_EVENT_SERVICE_PRIVATE_STORE = new WeakMap();
+var NB_EVENT_SERVICE_PRIVATE_LAZY = new WeakMap();
+
+// setup a base class to put all the don't know where to put methods
+
+var BaseClass = function BaseClass() {};
+
+var prototypeAccessors = { $name: { configurable: true },is: { configurable: true } };
/**
- * start suspend
- * @return {void}
+ * logger function for overwrite
*/
-SuspendClass.prototype.$suspend = function $suspend () {
- this.logger("---> SUSPEND ALL OPS <---");
- this.__suspend__(true);
+BaseClass.prototype.logger = function logger () {};
+
+// for id if the instance is this class
+prototypeAccessors.$name.get = function () {
+ return 'to1source-event'
};
-/**
- * release the queue
- * @return {void}
- */
-SuspendClass.prototype.$release = function $release () {
- this.logger("---> RELEASE SUSPENDED QUEUE <---");
- this.__suspend__(false);
+// take this down in the next release
+prototypeAccessors.is.get = function () {
+ return this.$name
};
/**
- * suspend event by pattern
- * @param {string} pattern the pattern search matches the event name
- * @return {void}
+ * validate the event name(s)
+ * @param {string[]} evt event name
+ * @return {boolean} true when OK
*/
-SuspendClass.prototype.$suspendEvent = function $suspendEvent (pattern) {
- var regex = getRegex(pattern);
- if (isRegExp(regex)) {
- this.__pattern__ = regex;
- return this.$suspend()
- }
- throw new Error(("We expect a pattern variable to be string or RegExp, but we got \"" + (typeof regex) + "\" instead"))
+BaseClass.prototype.validateEvt = function validateEvt () {
+ var this$1 = this;
+ var evt = [], len = arguments.length;
+ while ( len-- ) evt[ len ] = arguments[ len ];
+
+ evt.forEach(function (e) {
+ if (!isString$2(e)) {
+ this$1.logger('(validateEvt)', e);
+
+ throw new Error(("Event name must be string type! we got " + (typeof e)))
+ }
+ });
+
+ return true
};
/**
- * queuing call up when it's in suspend mode
- * @param {string} evt the event name
- * @param {*} args unknown number of arguments
- * @return {boolean} true when added or false when it's not
+ * Simple quick check on the two main parameters
+ * @param {string} evt event name
+ * @param {function} callback function to call
+ * @return {boolean} true when OK
*/
-SuspendClass.prototype.$queue = function $queue (evt) {
- var args = [], len = arguments.length - 1;
- while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+BaseClass.prototype.validate = function validate (evt, callback) {
+ if (this.validateEvt(evt)) {
+ if (typeof callback === 'function') {
- this.logger('($queue) get called');
- if (this.__suspend_state__ === true) {
- if (isRegExp(this.__pattern__)) { // it's better then check if its not null
- // check the pattern and decide if we want to suspend it or not
- var found = this.__pattern__.test(evt);
- if (!found) {
- return false
- }
+ return true
}
- this.logger('($queue) added to $queue', args);
- // @TODO there shouldn't be any duplicate, but how to make sure?
- this.queueStore.add([evt].concat(args));
- // return this.queueStore.size
}
- return !!this.__suspend_state__
+ throw new Error(("callback required to be function type! we got " + (typeof callback)))
};
/**
- * a getter to get all the store queue
- * @return {array} Set turn into Array before return
+ * Check if this type is correct or not added in V1.5.0
+ * @param {string} type for checking
+ * @return {boolean} true on OK
*/
-prototypeAccessors.$queues.get = function () {
- var size = this.queueStore.size;
- this.logger('($queues)', ("size: " + size));
- if (size > 0) {
- return Array.from(this.queueStore)
- }
- return []
+BaseClass.prototype.validateType = function validateType (type) {
+ this.validateEvt(type);
+
+ return !!AVAILABLE_TYPES.filter(function (t) { return type === t; }).length
};
/**
- * to set the suspend and check if it's boolean value
- * @param {boolean} value to trigger
+ * 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
*/
-SuspendClass.prototype.__suspend__ = function __suspend__ (value) {
- if (typeof value === 'boolean') {
- var lastValue = this.__suspend_state__;
- this.__suspend_state__ = value;
- this.logger(("($suspend) Change from \"" + lastValue + "\" --> \"" + value + "\""));
- if (lastValue === true && value === false) {
- this.__release__();
- }
- } else {
- throw new Error(("$suspend only accept Boolean value! we got " + (typeof value)))
- }
+BaseClass.prototype.run = function run (callback, payload, ctx) {
+ this.logger('(run) callback:', callback, 'payload:', payload, 'context:', ctx);
+ this.$done = Reflect.apply(callback, ctx, this.toArray(payload));
+
+ return this.$done // return it here first
};
/**
- * Release the queue
- * @return {int} size if any
+ * 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
*/
-SuspendClass.prototype.__release__ = function __release__ () {
- var this$1 = this;
+BaseClass.prototype.hashFnToKey = function hashFnToKey (fn) {
- var size = this.queueStore.size;
- var pattern = this.__pattern__;
- this.__pattern__ = null;
- this.logger(("(release) was called with " + size + (pattern ? ' for "' + pattern + '"': '') + " item" + (size > 1 ? 's' : '')));
- if (size > 0) {
- var queue = Array.from(this.queueStore);
- this.queueStore.clear();
- this.logger('(release 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)));
+ return hashCode2Str(fn.toString())
+};
+
+Object.defineProperties( BaseClass.prototype, prototypeAccessors );
+
+// making all the functionality on it's own
+
+var SuspendClass = /*@__PURE__*/(function (BaseClass) {
+ function SuspendClass() {
+ BaseClass.call(this);
+
+ // suspend, release and queue
+ this.__suspend_state__ = null;
+ // to do this proper we don't use a new prop to hold the event name pattern
+ this.__pattern__ = null;
+
+
+ this.queueStore = new Set();
}
- return size
-};
+ if ( BaseClass ) SuspendClass.__proto__ = BaseClass;
+ SuspendClass.prototype = Object.create( BaseClass && BaseClass.prototype );
+ SuspendClass.prototype.constructor = SuspendClass;
+
+ var prototypeAccessors = { $queues: { configurable: true } };
-Object.defineProperties( SuspendClass.prototype, prototypeAccessors );
+ /**
+ * start suspend
+ * @return {void}
+ */
+ SuspendClass.prototype.$suspend = function $suspend () {
+ this.logger("---> SUSPEND ALL OPS <---");
+ this.__suspend__(true);
+ };
+
+ /**
+ * release the queue
+ * @return {void}
+ */
+ SuspendClass.prototype.$release = function $release () {
+ this.logger("---> RELEASE SUSPENDED QUEUE <---");
+ this.__suspend__(false);
+ };
+
+ /**
+ * suspend event by pattern
+ * @param {string} pattern the pattern search matches the event name
+ * @return {void}
+ */
+ SuspendClass.prototype.$suspendEvent = function $suspendEvent (pattern) {
+ var regex = getRegex(pattern);
+ if (isRegExp(regex)) {
+ this.__pattern__ = regex;
+ return this.$suspend()
+ }
+ throw new Error(("We expect a pattern variable to be string or RegExp, but we got \"" + (typeof regex) + "\" instead"))
+ };
+
+ /**
+ * queuing call up when it's in suspend mode
+ * @param {string} evt the event name
+ * @param {*} args unknown number of arguments
+ * @return {boolean} true when added or false when it's not
+ */
+ SuspendClass.prototype.$queue = function $queue (evt) {
+ var args = [], len = arguments.length - 1;
+ while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+
+ this.logger('($queue) get called');
+ if (this.__suspend_state__ === true) {
+ if (isRegExp(this.__pattern__)) { // it's better then check if its not null
+ // check the pattern and decide if we want to suspend it or not
+ var found = this.__pattern__.test(evt);
+ if (!found) {
+ return false
+ }
+ }
+ this.logger('($queue) added to $queue', args);
+ // @TODO there shouldn't be any duplicate, but how to make sure?
+ this.queueStore.add([evt].concat(args));
+ // return this.queueStore.size
+ }
+ return !!this.__suspend_state__
+ };
+
+ /**
+ * a getter to get all the store queue
+ * @return {array} Set turn into Array before return
+ */
+ prototypeAccessors.$queues.get = function () {
+ var size = this.queueStore.size;
+ this.logger('($queues)', ("size: " + size));
+ if (size > 0) {
+ return Array.from(this.queueStore)
+ }
+ return []
+ };
+
+ /**
+ * to set the suspend and check if it's boolean value
+ * @param {boolean} value to trigger
+ */
+ SuspendClass.prototype.__suspend__ = function __suspend__ (value) {
+ if (typeof value === 'boolean') {
+ var lastValue = this.__suspend_state__;
+ this.__suspend_state__ = value;
+ this.logger(("($suspend) Change from \"" + lastValue + "\" --> \"" + value + "\""));
+ if (lastValue === true && value === false) {
+ this.__release__();
+ }
+ } else {
+ throw new Error(("$suspend only accept Boolean value! we got " + (typeof value)))
+ }
+ };
+
+ /**
+ * Release the queue
+ * @return {int} size if any
+ */
+ SuspendClass.prototype.__release__ = function __release__ () {
+ var this$1 = this;
+
+ var size = this.queueStore.size;
+ var pattern = this.__pattern__;
+ this.__pattern__ = null;
+ this.logger(("(release) was called with " + size + (pattern ? ' for "' + pattern + '"': '') + " item" + (size > 1 ? 's' : '')));
+ if (size > 0) {
+ var queue = Array.from(this.queueStore);
+ this.queueStore.clear();
+ this.logger('(release 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)));
+ }
+
+ return size
+ };
+
+ Object.defineProperties( SuspendClass.prototype, prototypeAccessors );
+
+ return SuspendClass;
+}(BaseClass));
// break up the main file because its getting way too long
@@ -6355,6 +6511,8 @@ var StoreService = /*@__PURE__*/(function (SuspendClass) {
// we need to init the store first otherwise it could be a lot of checking later
this.normalStore = new Map();
this.lazyStore = new Map();
+ // this is the new throw away map
+ this.maxCountStore = new Map();
}
if ( SuspendClass ) StoreService.__proto__ = SuspendClass;
@@ -6364,60 +6522,70 @@ var StoreService = /*@__PURE__*/(function (SuspendClass) {
var prototypeAccessors = { normalStore: { configurable: true },lazyStore: { configurable: true } };
/**
- * validate the event name(s)
- * @param {string[]} evt event name
- * @return {boolean} true when OK
+ * We need this to pre-check the store, otherwise
+ * the execution will be unable to determine the number of calls
+ * @param {string} evtName event name
+ * @return {number} the count of this store
*/
- StoreService.prototype.validateEvt = function validateEvt () {
- var this$1 = this;
- var evt = [], len = arguments.length;
- while ( len-- ) evt[ len ] = arguments[ len ];
-
- evt.forEach(function (e) {
- if (!isString$2(e)) {
- this$1.logger('(validateEvt)', e);
- throw new Error(("Event name must be string type! we got " + (typeof e)))
- }
- });
- return true
+ StoreService.prototype.getMaxStore = function getMaxStore (evtName) {
+ return this.maxCountStore.get(evtName) || NEG_RETURN
};
/**
- * Simple quick check on the two main parameters
- * @param {string} evt event name
- * @param {function} callback function to call
- * @return {boolean} true when OK
+ * This is one stop shop to check and munipulate the maxStore
+ * @param {*} evtName
+ * @param {*} [max=null]
+ * @return {number} when return -1 means removed
*/
- StoreService.prototype.validate = function validate (evt, callback) {
- if (this.validateEvt(evt)) {
- if (typeof callback === 'function') {
- return true
+ StoreService.prototype.checkMaxStore = function checkMaxStore (evtName, max) {
+ if ( max === void 0 ) max = null;
+
+ this.logger("===========================================");
+ this.logger('checkMaxStore start', evtName, max);
+ // init the store
+ if (max !== null && isInt(max)) {
+ // because this is the setup phrase we just return the max value
+ this.maxCountStore.set(evtName, max);
+ this.logger(("Setup max store for " + evtName + " with " + max));
+ return max
+ }
+ if (max === null) {
+ // first check if this exist in the maxStore
+ var value = this.getMaxStore(evtName);
+
+ this.logger('getMaxStore value', value);
+
+ if (value !== NEG_RETURN) {
+ if (value > 0) {
+ --value;
+ }
+ if (value > 0) {
+ this.maxCountStore.set(evtName, value); // just update the value
+ } else {
+ this.maxCountStore.delete(evtName); // just remove it
+ this.logger(("remove " + evtName + " from maxStore"));
+ return NEG_RETURN
+ }
}
+ return value
}
- throw new Error(("callback required to be function type! we got " + (typeof callback)))
+ throw new Error(("Expect max to be an integer, but we got " + (typeof max) + " " + max))
};
/**
- * Check if this type is correct or not added in V1.5.0
- * @param {string} type for checking
- * @return {boolean} true on OK
+ * Wrap several get filter ops together to return the callback we are looking for
+ * @param {string} evtName to search for
+ * @return {array} empty array when not found
*/
- StoreService.prototype.validateType = function validateType (type) {
- this.validateEvt(type);
- var types = ['on', 'only', 'once', 'onlyOnce'];
- return !!types.filter(function (t) { return type === t; }).length
- };
+ StoreService.prototype.searchMapEvt = function searchMapEvt (evtName) {
+ var evts = this.$get(evtName, true); // return in full
+ var search = evts.filter(function (result) {
+ var type = result[3];
- /**
- * 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
- */
- StoreService.prototype.run = function run (callback, payload, ctx) {
- this.logger('(run) callback:', callback, 'payload:', payload, 'context:', ctx);
- this.$done = Reflect.apply(callback, ctx, this.toArray(payload));
+ return inArray$2(ON_MAX_TYPES, type)
+ });
+
+ return search.length ? search : []
};
/**
@@ -6432,12 +6600,15 @@ var StoreService = /*@__PURE__*/(function (SuspendClass) {
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
}
throw new Error(("\"" + storeName + "\" is not supported!"))
@@ -6461,8 +6632,8 @@ var StoreService = /*@__PURE__*/(function (SuspendClass) {
if (full) {
return l
}
- var key = l[0];
var callback = l[1];
+
return callback
})
}
@@ -6478,23 +6649,21 @@ var StoreService = /*@__PURE__*/(function (SuspendClass) {
StoreService.prototype.removeFromStore = function removeFromStore (evt, store) {
if (store.has(evt)) {
this.logger('($off)', evt);
+
store.delete(evt);
- return true
+
+ return true
}
return false
};
/**
- * The add to store step is similar so make it generic for resuse
- * @param {object} store which store to use
+ * Take out from addToStore for reuse
+ * @param {object} store the 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
+ * @return {object} the set within the store
*/
- StoreService.prototype.addToStore = function addToStore (store, evt) {
- var args = [], len = arguments.length - 2;
- while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ];
-
+ StoreService.prototype.getStoreSet = function getStoreSet (store, evt) {
var fnSet;
if (store.has(evt)) {
this.logger(("(addToStore) \"" + evt + "\" existed"));
@@ -6504,6 +6673,21 @@ var StoreService = /*@__PURE__*/(function (SuspendClass) {
// this is new
fnSet = new Set();
}
+ return fnSet
+ };
+
+ /**
+ * 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
+ */
+ StoreService.prototype.addToStore = function addToStore (store, evt) {
+ var args = [], len = arguments.length - 2;
+ while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ];
+
+ var fnSet = this.getStoreSet(store, evt);
// 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) {
@@ -6523,6 +6707,7 @@ var StoreService = /*@__PURE__*/(function (SuspendClass) {
fnSet.add(args);
}
store.set(evt, fnSet);
+
return [store, fnSet.size]
};
@@ -6566,8 +6751,11 @@ var StoreService = /*@__PURE__*/(function (SuspendClass) {
StoreService.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 (li) {
@@ -6575,6 +6763,7 @@ var StoreService = /*@__PURE__*/(function (SuspendClass) {
return t !== type
}).length
}
+
return false
};
@@ -6593,15 +6782,19 @@ var StoreService = /*@__PURE__*/(function (SuspendClass) {
this.logger(("(addToNormalStore) try to add \"" + type + "\" --> \"" + evt + "\" to normal store"));
// @TODO we need to check the existing store for the type first!
if (this.checkTypeInStore(evt, type)) {
+
this.logger('(addToNormalStore)', ("\"" + type + "\" --> \"" + evt + "\" can add to 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
};
@@ -6631,6 +6824,7 @@ var StoreService = /*@__PURE__*/(function (SuspendClass) {
var size = ref[1];
this.lazyStore = _store;
this.logger(("(addToLazyStore) size: " + size));
+
return size
};
@@ -6673,16 +6867,6 @@ var StoreService = /*@__PURE__*/(function (SuspendClass) {
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
- */
- StoreService.prototype.hashFnToKey = function hashFnToKey (fn) {
- return hashCode2Str(fn.toString())
- };
-
Object.defineProperties( StoreService.prototype, prototypeAccessors );
return StoreService;
@@ -6701,22 +6885,7 @@ var EventService = /*@__PURE__*/(function (StoreService) {
EventService.prototype = Object.create( StoreService && StoreService.prototype );
EventService.prototype.constructor = EventService;
- var prototypeAccessors = { $name: { configurable: true },is: { configurable: true },$done: { configurable: true } };
-
- /**
- * logger function for overwrite
- */
- EventService.prototype.logger = function logger () {};
-
- // for id if the instance is this class
- prototypeAccessors.$name.get = function () {
- return 'to1source-event'
- };
-
- // take this down in the next release
- prototypeAccessors.is.get = function () {
- return this.$name
- };
+ var prototypeAccessors = { $done: { configurable: true } };
//////////////////////////
// PUBLIC METHODS //
@@ -6778,14 +6947,14 @@ var EventService = /*@__PURE__*/(function (StoreService) {
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;
+ // let nStore = this.normalStore
if (lazyStoreContent === false) {
this.logger(("($once) \"" + evt + "\" is not in the lazy store"));
// v1.3.0 $once now allow to add multiple listeners
- return this.addToNormalStore(evt, type, callback, context)
+ return this.addToNormalStore(evt, ONCE_TYPE, callback, context)
} else {
// now this is the tricky bit
// there is a potential bug here that cause by the developer
@@ -6799,7 +6968,7 @@ var EventService = /*@__PURE__*/(function (StoreService) {
var payload = ref[0];
var ctx = ref[1];
var t = ref[2];
- if (t && t !== type) {
+ if (t && t !== ONCE_TYPE) {
throw new Error((TAKEN_BY_OTHER_TYPE_ERR + " " + t))
}
this.logger('($once)', ("call run \"" + evt + "\""));
@@ -6821,15 +6990,18 @@ var EventService = /*@__PURE__*/(function (StoreService) {
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 normalStore"));
- added = this.addToNormalStore(evt, type, callback, context);
+
+ added = this.addToNormalStore(evt, ONLY_TYPE, callback, context);
}
+
if (lazyStoreContent !== false) {
// there are data store in lazy store
this.logger(("($only) \"" + evt + "\" found data in lazy store to execute"));
@@ -6839,13 +7011,14 @@ var EventService = /*@__PURE__*/(function (StoreService) {
var payload = li[0];
var ctx = li[1];
var t = li[2];
- if (t && t !== type) {
+ if (t && t !== ONLY_TYPE) {
throw new Error((TAKEN_BY_OTHER_TYPE_ERR + " " + t))
}
this$1.logger(("($only) call run \"" + evt + "\""));
this$1.run(callback, payload, context || ctx);
});
}
+
return added
};
@@ -6861,15 +7034,17 @@ var EventService = /*@__PURE__*/(function (StoreService) {
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 normalStore"));
- added = this.addToNormalStore(evt, type, callback, context);
+
+ added = this.addToNormalStore(evt, ONLY_ONCE_TYPE, callback, context);
}
+
if (lazyStoreContent !== false) {
// there are data store in lazy store
this.logger('($onlyOnce)', lazyStoreContent);
@@ -6879,10 +7054,11 @@ var EventService = /*@__PURE__*/(function (StoreService) {
var payload = ref[0];
var ctx = ref[1];
var t = ref[2];
- if (t && t !== 'onlyOnce') {
+ if (t && t !== ONLY_ONCE_TYPE) {
throw new Error((TAKEN_BY_OTHER_TYPE_ERR + " " + t))
}
this.logger(("($onlyOnce) call run \"" + evt + "\""));
+
this.run(callback, payload, context || ctx);
// remove this evt from store
this.$off(evt);
@@ -6890,6 +7066,67 @@ var EventService = /*@__PURE__*/(function (StoreService) {
return added
};
+ /**
+ * change the way how it suppose to work, instead of create another new store
+ * We perform this check on the trigger end, so we set the number max
+ * whenever we call the callback, we increment a value in the store
+ * once it reaches that number we remove that event from the store,
+ * also this will not get add to the lazy store,
+ * which means the event must register before we can fire it
+ * therefore we don't have to deal with the backward check
+ * @param {string} evtName the event to get pre-registered
+ * @param {number} max pass the max amount of callback can add to this event
+ * @param {*} [ctx=null] the context the callback execute in
+ * @return {function} the event handler
+ */
+ EventService.prototype.$max = function $max (evtName, max, ctx) {
+ if ( ctx === void 0 ) ctx = null;
+
+ this.validateEvt(evtName);
+ if (isInt(max) && max > 0) {
+ // find this in the normalStore
+ var fnSet = this.$get(evtName, true);
+ if (fnSet !== false) {
+ var evts = this.searchMapEvt(evtName);
+ if (evts.length) {
+ // should only have one anyway
+ var ref = evts[0];
+ var type = ref[3];
+ // now init the max store
+ var value = this.checkMaxStore(evtName, max);
+ var _self = this;
+ /**
+ * construct the callback
+ * @param {array<*>} args
+ * @return {number}
+ */
+ return function executeMaxCall() {
+ var args = [], len = arguments.length;
+ while ( len-- ) args[ len ] = arguments[ len ];
+
+ var ctn = _self.getMaxStore(evtName);
+ var value = NEG_RETURN;
+ if (ctn > 0) {
+ var fn = _self.$call(evtName, type, ctx);
+ Reflect.apply(fn, _self, args);
+
+ value = _self.checkMaxStore(evtName);
+ if (value === NEG_RETURN) {
+ _self.$off(evtName);
+ return NEG_RETURN
+ }
+ }
+ return value
+ }
+ }
+ }
+ // change in 1.1.1 because we might just call it without knowing if it's register or not
+ this.logger(("The " + evtName + " is not registered, can not execute non-existing event at the moment"));
+ return NEG_RETURN
+ }
+ throw new Error(("Expect max to be an integer and greater than zero! But we got [" + (typeof max) + "]" + max + " instead"))
+ };
+
/**
* This is a shorthand of $off + $on added in V1.5.0
* @param {string} evt event name
@@ -6900,12 +7137,14 @@ var EventService = /*@__PURE__*/(function (StoreService) {
*/
EventService.prototype.$replace = function $replace (evt, callback, context, type) {
if ( context === void 0 ) context = null;
- if ( type === void 0 ) type = 'on';
+ if ( type === void 0 ) type = ON_TYPE;
if (this.validateType(type)) {
this.$off(evt);
var method = this['$' + type];
+
this.logger("($replace)", evt, callback);
+
return Reflect.apply(method, this, [evt, callback, context])
}
throw new Error((type + " is not supported!"))
@@ -6940,6 +7179,7 @@ var EventService = /*@__PURE__*/(function (StoreService) {
var nSet = Array.from(nStore.get(evt));
var ctn = nSet.length;
var hasOnce = false;
+ // let hasOnly = false
for (var i=0; i < ctn; ++i) {
++found;
// this.logger('found', found)
@@ -6947,10 +7187,12 @@ var EventService = /*@__PURE__*/(function (StoreService) {
var _ = ref[0];
var callback = ref[1];
var ctx = ref[2];
- var type$1 = ref[3];
- this.logger(("($trigger) call run for " + evt));
+ var _type = ref[3];
+ this.logger(("($trigger) call run for " + type + ":" + evt));
+
this.run(callback, payload, context || ctx);
- if (type$1 === 'once' || type$1 === 'onlyOnce') {
+
+ if (_type === 'once' || _type === 'onlyOnce') {
hasOnce = true;
}
}
@@ -6979,11 +7221,12 @@ var EventService = /*@__PURE__*/(function (StoreService) {
var ctx = this;
- return function () {
+ return function executeCall() {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
var _args = [evt, args, context, type];
+
return Reflect.apply(ctx.$trigger, ctx, _args)
}
};
@@ -7311,8 +7554,6 @@ function createResolver(ee, namespace, resolverName, params, log) {
}
}
-
-
/**
* The first one in the chain, just setup a namespace prop
* the rest are passing through
@@ -7669,7 +7910,10 @@ function setupConnectedEvtListener(client, opts, ee) {
var obj;
client[CONNECTED_PROP_KEY] = true;
- log("CONNECTED_EVENT_NAME", true);
+ // new action to take release the holded event queue
+ var ctn = ee.$release();
+
+ log("CONNECTED_EVENT_NAME", true, 'queue count', ctn);
return ( obj = {}, obj[CONNECTED_PROP_KEY] = true, obj )
});
@@ -7769,7 +8013,11 @@ function setupFinalStep(obj, opts, ee) {
// now at this point, we are going to call the connect event
ee.$trigger(CONNECT_EVENT_NAME, [opts, ee]); // just passing back the entire opts object
-
+ // also we can release the queue here
+ if (opts[SUSPEND_EVENT_PROP_KEY] === true) {
+ opts.$releaseNamespace();
+ }
+
return client
}
@@ -7828,6 +8076,7 @@ configCheckMap[TOKEN_PROP_KEY] = createConfig$1(false, [STRING_TYPE]);
configCheckMap.loginMethod = createConfig$1(IO_HANDSHAKE_LOGIN, [STRING_TYPE], ( obj$1 = {}, obj$1[ENUM_KEY] = AVAILABLE_METHODS, obj$1 ));
configCheckMap.useJwt = createConfig$1(true, [BOOLEAN_TYPE, STRING_TYPE]);
configCheckMap.authStrKey = createConfig$1(null, [STRING_TYPE]);
+configCheckMap[SUSPEND_EVENT_PROP_KEY] = createConfig$1(false, [BOOLEAN_TYPE]);
// socket client
var socketCheckMap = {};
@@ -7886,7 +8135,7 @@ function postCheckInjectOpts(opts) {
opts.log = getLogFn(opts);
opts.eventEmitter = getEventEmitter(opts);
-
+
return opts
})
}
@@ -7905,6 +8154,21 @@ function createRequiredParams(opts) {
var nspMap = getNspInfoByConfig(opts);
var ee = opts.eventEmitter;
// @TODO here we are going to add suspend event to the namespace related methods
+ var log = opts.log;
+ var namespaces = nspMap.namespaces;
+
+ log("namespaces", namespaces);
+
+ // next we loop the namespace and suspend all the events prefix with namespace
+ if (opts[SUSPEND_EVENT_PROP_KEY] === true) {
+ // we create this as a function then we can call it again
+ opts.$suspendNamepsace = function () { return namespaces.forEach(function (namespace) { return ee.$suspendEvent(namespace); }); };
+ // then we create a new method to releas the queue
+ // we prefix it with the $ to notify this is not a jsonql part methods
+ opts.$releaseNamespace = function () { return ee.$release(); };
+ // now run it
+ opts.$suspendNamepsace();
+ }
return { opts: opts, nspMap: nspMap, ee: ee }
}
@@ -7935,7 +8199,7 @@ function wsClientCoreAction(setupSocketClientListener) {
var nspMap = ref.nspMap;
var ee = ref.ee;
- return setupSocketClientListener(opts, nspMap, ee, 'jsonql-ws-client-core');
+ return setupSocketClientListener(opts, nspMap, ee);
}
)
.then(
@@ -8051,6 +8315,30 @@ var handleNamespaceOnError = function (ee, namespace, err) {
// NOT IN USE AT THE MOMENT JUST KEEP IT HERE FOR THE TIME BEING
+/**
+ * A Event Listerner placeholder when it's not connect to the private nsp
+ * @param {string} namespace nsp
+ * @param {object} ee EventEmitter
+ * @param {object} opts configuration
+ * @return {void}
+ */
+var notLoginListener = function (namespace, ee, opts) {
+ var log = opts.log;
+
+ ee.$only(
+ createEvt(namespace, EMIT_EVT),
+ function notLoginListernerCallback(resolverName, args) {
+ log('[notLoginListerner] hijack the ws call', namespace, resolverName, args);
+ var error = { message: NOT_LOGIN_ERR_MSG };
+ // It should just throw error here and should not call the result
+ // because that's channel for handling normal event not the fake one
+ ee.$call(createEvt(namespace, resolverName, ON_ERROR_FN_NAME), [ error ]);
+ // also trigger the result Listerner, but wrap inside the error key
+ ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error: error }]);
+ }
+ );
+};
+
/**
* Only when there is a private namespace then we bind to this event
* @param {object} nsps the available nsp(s)
@@ -8086,30 +8374,6 @@ var logoutEvtListener = function (nsps, namespaces, ee, opts) {
);
};
-/**
- * A Event Listerner placeholder when it's not connect to the private nsp
- * @param {string} namespace nsp
- * @param {object} ee EventEmitter
- * @param {object} opts configuration
- * @return {void}
- */
-var notLoginListener = function (namespace, ee, opts) {
- var log = opts.log;
-
- ee.$only(
- createEvt(namespace, EMIT_EVT),
- function notLoginListernerCallback(resolverName, args) {
- log('[notLoginListerner] hijack the ws call', namespace, resolverName, args);
- var error = { message: NOT_LOGIN_ERR_MSG };
- // It should just throw error here and should not call the result
- // because that's channel for handling normal event not the fake one
- ee.$call(createEvt(namespace, resolverName, ON_ERROR_FN_NAME), [ error ]);
- // also trigger the result Listerner, but wrap inside the error key
- ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error: error }]);
- }
- );
-};
-
// This is share between different clients so we export it
/**
@@ -8135,6 +8399,8 @@ function namespaceEventListener(bindSocketEventListener, nsps) {
// then we can use this prop to determine if we need to fire the ON_LOGIN_PROP_NAME event
var privateNamespace = getPrivateNamespace$1(namespaces);
+ // @TODO hook up the connectedEvtHandler somewhere
+
return namespaces.map(function (namespace) {
var isPrivate = privateNamespace === namespace;
log(namespace, (" --> " + (isPrivate ? 'private': 'public') + " nsp --> "), nsps[namespace] !== false);
@@ -8144,7 +8410,7 @@ function namespaceEventListener(bindSocketEventListener, nsps) {
var args = [namespace, nsps[namespace], ee, isPrivate, opts];
// Finally we binding everything together
Reflect.apply(bindSocketEventListener, null, args);
-
+
} else {
log(("binding notLoginWsHandler to " + namespace));
// a dummy placeholder
@@ -8182,14 +8448,14 @@ var WS_DATA_NAME$1 = '__data__';
// for ws client, 1.9.3 breaking change to name them as FN instead of PROP
var ON_MESSAGE_FN_NAME$1 = 'onMessage';
-var ON_RESULT_FN_NAME$1 = 'onResult';
+var ON_RESULT_FN_NAME$1 = 'onResult'; // this will need to be internal from now on
var ON_ERROR_FN_NAME$1 = 'onError';
var ON_READY_FN_NAME$1 = 'onReady';
var ON_LOGIN_FN_NAME$1 = 'onLogin'; // new @1.8.6
// this is somewhat vague about what is suppose to do
var EMIT_REPLY_TYPE$1 = 'emit_reply';
-var ACKNOWLEDGE_REPLY_TYPE = 'acknowledge_reply';
+var ACKNOWLEDGE_REPLY_TYPE = 'emit_acknowledge';
var JS_WS_NAME = 'ws';
var TOKEN_PARAM_NAME = 'token';
@@ -8266,10 +8532,14 @@ function asyncConnect(WebSocket, url, options) {
* therefore the object was pass as second parameter!
* @NOTE here we only return a method to create the client, it might not get call
* @param {object} WebSocket the client or node version of ws
- * @param {boolean} auth if it's auth then 3 param or just one
* @param {object} opts this is a breaking change we will init the client twice
+ * @param {boolean} [auth = false] if it's auth then 3 param or just one
+ * @return {function} the client method to connect to the ws socket server
*/
-function initWebSocketClient(WebSocket, auth, log) {
+function initWebSocketClient(WebSocket, opts, auth) {
+ if ( auth === void 0 ) auth = false;
+
+ var log = opts.log;
if (auth === false) {
/**
* Create a non-protected client
@@ -10522,7 +10792,7 @@ var createNsp = function(opts, nspMap, token) {
* @param {*} value to check against
* @return {boolean} true on found
*/
-var inArray$2 = function (arr, value) { return !!arr.filter(function (a) { return a === value; }).length; };
+var inArray$3 = function (arr, value) { return !!arr.filter(function (a) { return a === value; }).length; };
/**
* parse string to json or just return the original value if error happened
@@ -10551,7 +10821,7 @@ var parseJson$1 = function(n, t) {
var isObjectHasKey$2 = function(obj, key) {
try {
var keys = Object.keys(obj);
- return inArray$2(keys, key)
+ return inArray$3(keys, key)
} catch(e) {
// @BUG when the obj is not an OBJECT we got some weird output
return false
@@ -10719,14 +10989,16 @@ var formatPayload$1 = function (args) {
/**
* wrapper method to add the timestamp as well
- * @param {string} resolverName
- * @param {*} payload
+ * @param {string} resolverName name of the resolver
+ * @param {*} payload what is sending
+ * @param {object} extra additonal property we want to merge into the deliverable
* @return {object} delierable
*/
-function createDeliverable$1(resolverName, payload) {
+function createDeliverable$1(resolverName, payload, extra) {
var obj;
- return ( obj = {}, obj[resolverName] = payload, obj[TIMESTAMP_PARAM_NAME$1] = [ timestamp$1() ], obj )
+ if ( extra === void 0 ) extra = {};
+ return Object.assign(( obj = {}, obj[resolverName] = payload, obj[TIMESTAMP_PARAM_NAME$1] = [ timestamp$1() ], obj ), extra)
}
/**
@@ -10746,7 +11018,11 @@ function createQuery$1(resolverName, args, jsonp) {
}
return createDeliverable$1(resolverName, payload)
}
- throw new JsonqlValidationError$1("[createQuery] expect resolverName to be string and args to be array!", { resolverName: resolverName, args: args })
+ throw new JsonqlValidationError$1('utils:params-api:createQuery', {
+ message: "expect resolverName to be string and args to be array!",
+ resolverName: resolverName,
+ args: args
+ })
}
/**
@@ -10797,7 +11073,7 @@ var extractWsPayload$1 = function (payload, cb) {
var _data;
if ((_data = isWsReply$1(json)) !== false) {
// note the ts property is on its own
- cb(TIMESTAMP_PARAM_NAME$1, json[TIMESTAMP_PARAM_NAME$1]);
+ cb('_data', _data);
return {
data: toJson$1(_data[WS_DATA_NAME$1]),
@@ -11006,24 +11282,23 @@ function connectEventListener(nspMap, ee, log) {
* @param {object} frameworkModule the different WebSocket module
* @return {function} the wsClientResolver
*/
-function bindFrameworkToJsonql(frameworkModule) {
+function bindWebsocketToJsonql(frameworkModule) {
/**
* wsClientResolver
* @param {object} opts configuration
* @param {object} nspMap from the contract
* @param {object} ee instance of the eventEmitter
- * @param {string} msg a message to id where the data coming from
* @return {object} passing the same 3 input out with additional in the opts
*/
- return function createClientBindingAction(opts, nspMap, ee, msg) {
+ return function createClientBindingAction(opts, nspMap, ee) {
var log = opts.log;
- log("Where the parameters coming from:", msg);
+ log("There is problem here with passing the opts", opts);
- opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log);
- opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log);
+ opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, opts);
+ opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, opts, true);
// debug
- log("[1] bindFrameworkToJsonql", ee.name, nspMap);
+ log("[1] bindWebsocketToJsonql", ee.$name, nspMap);
// @2020-03-20 @NOTE
connectEventListener(nspMap, ee, log);
@@ -11050,7 +11325,7 @@ function bindFrameworkToJsonql(frameworkModule) {
* @param {object} ee instance of the eventEmitter
* @return {object} passing the same 3 input out with additional in the opts
*/
-var setupSocketClientListener = bindFrameworkToJsonql(WebSocket);
+var setupSocketClientListener = bindWebsocketToJsonql(WebSocket);
// this is the module entry point for node client
diff --git a/packages/@jsonql/ws/main.js.map b/packages/@jsonql/ws/main.js.map
index df927896c5d2ff81c992f36a38f83935317f10a5..d0663bcd385568b38b8c24ffff9af6a7fbe9beab 100644
--- a/packages/@jsonql/ws/main.js.map
+++ b/packages/@jsonql/ws/main.js.map
@@ -1 +1 @@
-{"version":3,"file":"main.js","sources":["../../ws-client-core/node_modules/lodash-es/isArray.js","node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/lodash-es/_objectToString.js","../../ws-client-core/node_modules/lodash-es/_overArg.js","../../ws-client-core/node_modules/lodash-es/isObjectLike.js","../../ws-client-core/node_modules/lodash-es/_arrayMap.js","../../ws-client-core/node_modules/lodash-es/_baseSlice.js","../../ws-client-core/node_modules/lodash-es/_baseFindIndex.js","../../ws-client-core/node_modules/lodash-es/_baseIsNaN.js","../../ws-client-core/node_modules/lodash-es/_strictIndexOf.js","../../ws-client-core/node_modules/lodash-es/_asciiToArray.js","../../ws-client-core/node_modules/lodash-es/_hasUnicode.js","../../ws-client-core/node_modules/lodash-es/_unicodeToArray.js","../../ws-client-core/node_modules/jsonql-utils/src/generic.js","../../ws-client-core/node_modules/lodash-es/_listCacheClear.js","../../ws-client-core/node_modules/lodash-es/eq.js","../../ws-client-core/node_modules/lodash-es/_stackDelete.js","../../ws-client-core/node_modules/lodash-es/_stackGet.js","../../ws-client-core/node_modules/lodash-es/_stackHas.js","../../ws-client-core/node_modules/lodash-es/isObject.js","../../ws-client-core/node_modules/lodash-es/_toSource.js","../../ws-client-core/node_modules/lodash-es/_getValue.js","../../ws-client-core/node_modules/lodash-es/_hashDelete.js","../../ws-client-core/node_modules/lodash-es/_isKeyable.js","../../ws-client-core/node_modules/lodash-es/_createBaseFor.js","../../ws-client-core/node_modules/lodash-es/_copyArray.js","../../ws-client-core/node_modules/lodash-es/_isPrototype.js","../../ws-client-core/node_modules/lodash-es/isLength.js","../../ws-client-core/node_modules/lodash-es/stubFalse.js","../../ws-client-core/node_modules/lodash-es/_baseUnary.js","../../ws-client-core/node_modules/lodash-es/_safeGet.js","../../ws-client-core/node_modules/lodash-es/_baseTimes.js","../../ws-client-core/node_modules/lodash-es/_isIndex.js","../../ws-client-core/node_modules/lodash-es/_nativeKeysIn.js","../../ws-client-core/node_modules/lodash-es/identity.js","../../ws-client-core/node_modules/lodash-es/_apply.js","../../ws-client-core/node_modules/lodash-es/constant.js","../../ws-client-core/node_modules/lodash-es/_shortOut.js","../../ws-client-core/node_modules/jsonql-errors/src/enum-error.js","../../ws-client-core/node_modules/jsonql-errors/src/type-error.js","../../ws-client-core/node_modules/jsonql-errors/src/checker-error.js","../../ws-client-core/node_modules/jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/jsonql-utils/src/contract.js","../../ws-client-core/node_modules/jsonql-utils/src/timestamp.js","../../ws-client-core/node_modules/jsonql-utils/src/params-api.js","../../ws-client-core/node_modules/jsonql-utils/src/namespace.js","../../ws-client-core/node_modules/jsonql-utils/src/socket.js","../../ws-client-core/src/callers/intercom-methods.js","../../ws-client-core/node_modules/jsonql-params-validator/src/number.js","../../ws-client-core/node_modules/jsonql-params-validator/src/string.js","../../ws-client-core/node_modules/jsonql-params-validator/src/boolean.js","../../ws-client-core/node_modules/jsonql-params-validator/src/any.js","../../ws-client-core/node_modules/jsonql-params-validator/src/constants.js","../../ws-client-core/node_modules/jsonql-params-validator/src/combine.js","../../ws-client-core/node_modules/jsonql-params-validator/src/array.js","../../ws-client-core/node_modules/jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/jsonql-params-validator/src/validator.js","../../ws-client-core/node_modules/lodash-es/_setCacheAdd.js","../../ws-client-core/node_modules/lodash-es/_setCacheHas.js","../../ws-client-core/node_modules/lodash-es/_arraySome.js","../../ws-client-core/node_modules/lodash-es/_cacheHas.js","../../ws-client-core/node_modules/lodash-es/_mapToArray.js","../../ws-client-core/node_modules/lodash-es/_setToArray.js","../../ws-client-core/node_modules/lodash-es/_arrayPush.js","../../ws-client-core/node_modules/lodash-es/_arrayFilter.js","../../ws-client-core/node_modules/lodash-es/stubArray.js","../../ws-client-core/node_modules/lodash-es/_matchesStrictComparable.js","../../ws-client-core/node_modules/lodash-es/_baseHasIn.js","../../ws-client-core/node_modules/lodash-es/_baseProperty.js","../../ws-client-core/node_modules/lodash-es/negate.js","../../ws-client-core/node_modules/lodash-es/_baseFindKey.js","../../ws-client-core/node_modules/jsonql-params-validator/src/is-in-array.js","../../ws-client-core/node_modules/jsonql-params-validator/src/options/run-validation.js","../../ws-client-core/node_modules/jsonql-params-validator/src/options/check-options-async.js","../../ws-client-core/node_modules/jsonql-params-validator/src/options/construct-config.js","../../ws-client-core/node_modules/jsonql-params-validator/src/options/index.js","../../ws-client-core/node_modules/jsonql-params-validator/index.js","../../ws-client-core/src/utils/get-log-fn.js","../../ws-client-core/node_modules/@to1source/event/src/constants.js","../../ws-client-core/node_modules/@to1source/event/src/store.js","../../ws-client-core/node_modules/@to1source/event/src/utils.js","../../ws-client-core/node_modules/@to1source/event/src/suspend.js","../../ws-client-core/node_modules/@to1source/event/src/store-service.js","../../ws-client-core/node_modules/@to1source/event/src/event-service.js","../../ws-client-core/node_modules/@to1source/event/index.js","../../ws-client-core/src/utils/get-event-emitter.js","../../ws-client-core/src/utils/helpers.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/callers/respond-handler.js","../../ws-client-core/src/callers/action-call.js","../../ws-client-core/src/callers/setup-send-method.js","../../ws-client-core/src/callers/setup-resolver.js","../../ws-client-core/src/callers/generator-methods.js","../../ws-client-core/src/callers/global-listener.js","../../ws-client-core/src/callers/setup-auth-methods.js","../../ws-client-core/src/callers/setup-intercom.js","../../ws-client-core/src/callers/setup-final-step.js","../../ws-client-core/src/callers/callers-generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/listener/create-nsp-clients.js","../../ws-client-core/src/listener/trigger-namespaces-on-error.js","../../ws-client-core/src/listener/event-listeners.js","../../ws-client-core/src/listener/namespace-event-listener.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.js","src/core/listeners/login-event-listener.js","node_modules/lodash-es/_objectToString.js","node_modules/lodash-es/_overArg.js","node_modules/lodash-es/isObjectLike.js","node_modules/lodash-es/_listCacheClear.js","node_modules/lodash-es/eq.js","node_modules/lodash-es/_stackDelete.js","node_modules/lodash-es/_stackGet.js","node_modules/lodash-es/_stackHas.js","node_modules/lodash-es/isObject.js","node_modules/lodash-es/_toSource.js","node_modules/lodash-es/_getValue.js","node_modules/lodash-es/_hashDelete.js","node_modules/lodash-es/_isKeyable.js","node_modules/lodash-es/_createBaseFor.js","node_modules/lodash-es/_copyArray.js","node_modules/lodash-es/_isPrototype.js","node_modules/lodash-es/isArray.js","node_modules/lodash-es/isLength.js","node_modules/lodash-es/stubFalse.js","node_modules/lodash-es/_baseUnary.js","node_modules/lodash-es/_safeGet.js","node_modules/lodash-es/_baseTimes.js","node_modules/lodash-es/_isIndex.js","node_modules/lodash-es/_nativeKeysIn.js","node_modules/lodash-es/identity.js","node_modules/lodash-es/_apply.js","node_modules/lodash-es/constant.js","node_modules/lodash-es/_shortOut.js","node_modules/jsonql-utils/src/chain-promises.js","src/core/create-nsp.js","node_modules/jsonql-utils/src/generic.js","node_modules/jsonql-errors/src/validation-error.js","node_modules/jsonql-utils/src/timestamp.js","node_modules/jsonql-utils/src/params-api.js","node_modules/jsonql-utils/src/socket.js","src/core/listeners/disconnect-event-listener.js","src/core/listeners/bind-socket-event-handler.js","src/core/listeners/connect-event-listener.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/setup-socket-client-listener.js","src/node-ws-client.js"],"sourcesContent":["/**\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","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 * 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 * 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 * 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","/**\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","/**\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 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","/** 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","// bunch of generic helpers\n\nimport isArray from 'lodash-es/isArray'\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport trim from 'lodash-es/trim'\n\n/**\n * DIY in Array\n * @param {array} arr to check from\n * @param {*} value to check against\n * @return {boolean} true on found\n */\nexport const inArray = (arr, value) => !!arr.filter(a => a === value).length\n\n// quick and dirty to turn non array to array\nexport const toArray = (arg) => isArray(arg) ? arg : [arg]\n\n/**\n * parse string to json or just return the original value if error happened\n * @param {*} n input\n * @param {boolean} [t=true] or throw\n * @return {*} json object on success\n */\nexport const parseJson = function(n, t=true) {\n try {\n return JSON.parse(n)\n } catch(e) {\n if (t) {\n return n\n }\n throw new Error(e)\n }\n}\n\n/**\n * @param {object} obj for search\n * @param {string} key target\n * @return {boolean} true on success\n */\nexport const isObjectHasKey = function(obj, key) {\n try {\n const keys = Object.keys(obj)\n return inArray(keys, key)\n } catch(e) {\n // @BUG when the obj is not an OBJECT we got some weird output\n return false\n }\n}\n\n/**\n * create a event name\n * @param {string[]} args\n * @return {string} event name for use\n */\nexport const createEvt = (...args) => args.join('_')\n\n/**\n * simple util method to get the value\n * @param {string} name of the key\n * @param {object} obj to take value from\n * @return {*} the object value id by name or undefined\n */\nexport const getConfigValue = (name, obj) => (\n obj && isPlainObject(obj) ? ( (name in obj) ? obj[name] : undefined ) : undefined\n)\n\n/**\n * small util to make sure the return value is valid JSON object\n * @param {*} n input\n * @return {object} correct JSON object\n */\nexport const toJson = n => {\n if (typeof n === 'string') {\n return parseJson(n)\n }\n return parseJson(JSON.stringify(n))\n}\n\n/**\n * Check several parameter that there is something in the param\n * @param {*} param input\n * @return {boolean}\n */\nexport const isNotEmpty = function(param) {\n return param !== undefined && param !== false && param !== null && trim(param) !== ''\n}\n\n/**\n * Simple check if the prop is function\n * @param {*} prop input\n * @return {boolean} true on success\n */\nexport const isFunc = prop => {\n if (typeof prop === 'function') {\n return true;\n }\n console.error(`Expect to be Function type! Got ${typeof prop}`)\n}\n\n/**\n * Shorthand method for Object.assign \n * @param {array} args \n * @return {object} merge together object by key \n */\nexport const assign = (...args) => Reflect.apply(Object.assign, Object, args)\n \n/** \n * generic placeholder function\n * @return {boolean} false \n */\nexport const nil = () => false\n\n/**\n * generic turn config into immutatble \n */\nexport const freeze = config => Object.freeze(config)","/**\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 * 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","/**\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 * 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","/** 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 * 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 * 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 * 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 * 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 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","/** 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","/**\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 * 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 `_.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","/** 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 * 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 * 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","/**\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 * 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","/** 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","// 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","// split the contract into the node side and the generic side\nimport { isObjectHasKey } from './generic'\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport {\n QUERY_NAME,\n MUTATION_NAME,\n SOCKET_NAME,\n QUERY_ARG_NAME,\n PAYLOAD_PARAM_NAME,\n CONDITION_PARAM_NAME\n} from 'jsonql-constants'\nimport { JsonqlError, JsonqlResolverNotFoundError } from 'jsonql-errors'\n/**\n * Check if the json is a contract file or not\n * @param {object} contract json object\n * @return {boolean} true\n */\nexport function checkIsContract(contract) {\n return isPlainObject(contract)\n && (\n isObjectHasKey(contract, QUERY_NAME)\n || isObjectHasKey(contract, MUTATION_NAME)\n || isObjectHasKey(contract, SOCKET_NAME)\n )\n}\n\n/**\n * Wrapper method that check if it's contract then return the contract or false\n * @param {object} contract the object to check\n * @return {boolean | object} false when it's not\n */\nexport function isContract(contract) {\n return checkIsContract(contract) ? contract : false\n}\n\n/**\n * Ported from jsonql-params-validator but different\n * if we don't find the socket part then return false\n * @param {object} contract the contract object\n * @return {object|boolean} false on failed\n */\nexport function extractSocketPart(contract) {\n if (isObjectHasKey(contract, SOCKET_NAME)) {\n return contract[SOCKET_NAME]\n }\n return false\n}\n\n/**\n * Extract the args from the payload\n * @param {object} payload to work with\n * @param {string} type of call\n * @return {array} args\n */\nexport function extractArgsFromPayload(payload, type) {\n switch (type) {\n case QUERY_NAME:\n return payload[QUERY_ARG_NAME]\n case MUTATION_NAME:\n return [\n payload[PAYLOAD_PARAM_NAME],\n payload[CONDITION_PARAM_NAME]\n ]\n default:\n throw new JsonqlError(`Unknown ${type} to extract argument from!`)\n }\n}\n\n/**\n * Like what the name said\n * @param {object} contract the contract json\n * @param {string} type query|mutation\n * @param {string} name of the function\n * @return {object} the params part of the contract\n */\nexport function extractParamsFromContract(contract, type, name) {\n try {\n const result = contract[type][name]\n // debug('extractParamsFromContract', result)\n if (!result) {\n // debug(name, type, contract)\n throw new JsonqlResolverNotFoundError(name, type)\n }\n return result\n } catch(e) {\n throw new JsonqlResolverNotFoundError(name, e)\n }\n}\n","/**\n * @param {boolean} sec return in second or not\n * @return {number} timestamp\n */\nexport const timestamp = (sec = false) => {\n let time = Date.now()\n return sec ? Math.floor( time / 1000 ) : time\n}\n","// ported from jsonql-params-validator\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 TIMESTAMP_PARAM_NAME\n} from 'jsonql-constants'\n\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\n\nimport isArray from 'lodash-es/isArray'\nimport isString from 'lodash-es/isString'\nimport isPlainObject from 'lodash-es/isPlainObject'\n\nimport { timestamp } from './timestamp'\nimport { parseJson } from './generic'\n\n/**\n * check if the payload has a timestamp field, then append a new timestamp to it\n * @param {object} payload from the com\n * @return {array} timestamp field with an array value\n */\nexport const handleTimestamp = payload => {\n let ts = payload[TIMESTAMP_PARAM_NAME]\n if (!isArray(ts)) {\n ts = [ts]\n }\n ts.push( timestamp() )\n\n return ts\n}\n\n/**\n * make sure it's an object (it was call formatPayload but it doesn't make sense)\n * @param {*} payload the object comes in could be string based\n * @return {object} the transformed payload\n */\nexport const toPayload = payload => isString(payload) ? parseJson(payload) : payload\n\n/**\n * @param {*} args arguments to send\n *@return {object} formatted payload\n */\nexport const formatPayload = (args) => (\n { [QUERY_ARG_NAME]: args }\n)\n\n/**\n * extract the resolver name from the payload \n * @param {object} payload\n * @return {string} resolver name \n */\nexport function getResolverFromPayload(payload) {\n const keys = Object.keys(payload)\n return keys.filter(key => key !== TIMESTAMP_PARAM_NAME)[0]\n}\n\n/**\n * wrapper method to add the timestamp as well\n * @param {string} resolverName\n * @param {*} payload\n * @return {object} delierable\n */\nexport function createDeliverable(resolverName, payload) {\n return {\n [resolverName]: payload,\n [TIMESTAMP_PARAM_NAME]: [ timestamp() ]\n }\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) && isArray(args)) {\n let payload = formatPayload(args)\n if (jsonp === true) {\n return payload\n }\n return createDeliverable(resolverName, payload)\n }\n throw new JsonqlValidationError(`[createQuery] expect resolverName to be string and args to be array!`, { resolverName, args })\n}\n\n/**\n * string version of the createQuery\n * @return {string}\n */\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 createDeliverable(resolverName, _payload)\n }\n throw new JsonqlValidationError(`[createMutation] expect resolverName to be string!`, { resolverName, payload, condition })\n}\n\n/**\n * string version of createMutation\n * @return {string}\n */\nexport function createMutationStr(resolverName, payload, condition = {}, jsonp = false) {\n return JSON.stringify(createMutation(resolverName, payload, condition, jsonp))\n}\n\n/**\n * Extract the parts from payload and format for use\n * @param {string} resolverName name of fn\n * @param {object} payload the incoming json\n * @return {object|boolean} false on failed\n */\nexport function getQueryFromArgs(resolverName, payload) {\n if (resolverName && isPlainObject(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 [TIMESTAMP_PARAM_NAME]: handleTimestamp(payload)\n }\n }\n }\n return false\n}\n\n/**\n * Share function so no repeat\n * @param {object} payload the payload from client\n * @param {function} processor the last get result method\n * @return {*} result processed result\n */\nfunction processPayload(payload, processor) {\n const p = toPayload(payload)\n const resolverName = getResolverFromPayload(p)\n return Reflect.apply(processor, null, [resolverName, p])\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 result = processPayload(payload, getQueryFromArgs)\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 && isPlainObject(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 [TIMESTAMP_PARAM_NAME]: handleTimestamp(payload)\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 result = processPayload(payload, getMutationFromArgs)\n\n if (result !== false) {\n return result\n }\n throw new JsonqlValidationError('[getMutationArgs] Payload is malformed!', payload)\n}\n","// take out all the namespace related methods in one place for easy to find\nimport {\n JSONQL_PATH,\n PUBLIC_KEY,\n NSP_GROUP,\n PUBLIC_NAMESPACE\n} from 'jsonql-constants'\nimport { extractSocketPart } from './contract'\nconst SOCKET_NOT_FOUND_ERR = `socket not found in contract!`\nconst SIZE = 'size'\n\n/**\n * create the group using publicNamespace when there is only public\n * @param {object} socket from contract\n * @param {string} publicNamespace\n */\nfunction groupPublicNamespace(socket, publicNamespace) {\n let g = {}\n for (let resolverName in socket) {\n let params = socket[resolverName]\n g[resolverName] = params\n }\n return { size: 1, nspGroup: {[publicNamespace]: g}, publicNamespace}\n}\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 function groupByNamespace(contract) {\n let socket = extractSocketPart(contract)\n if (socket === false) {\n throw new JsonqlError('groupByNamespace', SOCKET_NOT_FOUND_ERR)\n }\n let prop = {\n [NSP_GROUP]: {},\n [PUBLIC_NAMESPACE]: null,\n [SIZE]: 0 \n }\n\n for (let resolverName in socket) {\n let params = socket[resolverName]\n let { namespace } = params\n if (namespace) {\n if (!prop[NSP_GROUP][namespace]) {\n ++prop[SIZE]\n prop[NSP_GROUP][namespace] = {}\n }\n prop[NSP_GROUP][namespace][resolverName] = params\n // get the public namespace\n if (!prop[PUBLIC_NAMESPACE] && params[PUBLIC_KEY]) {\n prop[PUBLIC_NAMESPACE] = namespace\n }\n }\n }\n \n return prop \n}\n\n/**\n * @NOTE ported from jsonql-ws-client\n * Got to make sure the connection order otherwise\n * it will hang\n * @param {object} nspGroup contract\n * @param {string} publicNamespace like the name said\n * @return {array} namespaces in order\n */\nexport function getNamespaceInOrder(nspGroup, publicNamespace) {\n let names = [] // need to make sure the order!\n for (let namespace in nspGroup) {\n if (namespace === publicNamespace) {\n names[1] = namespace\n } else {\n names[0] = namespace\n }\n }\n return names\n}\n\n/**\n * @TODO this might change, what if we want to do room with ws\n * 1. there will only be max two namespace\n * 2. when it's normal we will have the stock path as namespace\n * 3. when enableAuth then we will have two, one is jsonql/public + private\n * @param {object} config options\n * @return {array} of namespace(s)\n */\nexport function getNamespace(config) {\n const base = JSONQL_PATH\n if (config.enableAuth) {\n // the public come first @1.0.1 we use the constants instead of the user supplied value\n // @1.0.4 we use the config value again, because we could control this via the post init\n return [\n [ base , config.privateNamespace ].join('/'),\n [ base , config.publicNamespace ].join('/')\n ]\n }\n return [ base ]\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nexport function getPrivateNamespace(namespaces) {\n return namespaces.length > 1 ? namespaces[0] : false\n}\n\n/**\n * Got a problem with a contract that is public only the groupByNamespace is wrong\n * which is actually not a problem when using a fallback, but to be sure things in order\n * we could combine with the config to group it\n * @param {object} config configuration\n * @return {object} nspInfo object\n */\nexport function getNspInfoByConfig(config) {\n const { contract, enableAuth } = config\n const namespaces = getNamespace(config)\n let nspInfo = enableAuth ? groupByNamespace(contract)\n : groupPublicNamespace(contract.socket, namespaces[0])\n // add the namespaces into it as well\n return Object.assign(nspInfo, { namespaces })\n}\n\n","// There are the socket related methods ported back from \n// ws-server-core and ws-client-core \nimport {\n WS_REPLY_TYPE,\n WS_EVT_NAME,\n WS_DATA_NAME,\n TIMESTAMP_PARAM_NAME,\n ERROR_KEY,\n EMIT_REPLY_TYPE,\n ACKNOWLEDGE_REPLY_TYPE\n} from 'jsonql-constants'\nimport { JsonqlError } from 'jsonql-errors' \nimport isString from 'lodash-es/isString'\n\nimport { toJson, isObjectHasKey, nil } from './generic'\nimport { timestamp } from './timestamp'\n\nconst PAYLOAD_NOT_DECODED_ERR = 'payload can not decoded'\nconst WS_KEYS = [\n WS_REPLY_TYPE,\n WS_EVT_NAME,\n WS_DATA_NAME\n]\n\n/////////////////////////////////////\n// REPLY FROM SERVER //\n/////////////////////////////////////\n\n\n/**\n * The ws doesn't have a acknowledge callback like socket.io\n * so we have to DIY one for ws and other that doesn't have it\n * @param {string} type of reply\n * @param {string} resolverName which is replying\n * @param {*} data payload\n * @param {array} [ts= []] the last received ts, if any \n * @return {string} stringify json\n */\nexport const createWsReply = (type, resolverName, data, ts = []) => {\n ts.push(timestamp())\n return JSON.stringify({\n data: {\n [WS_REPLY_TYPE]: type,\n [WS_EVT_NAME]: resolverName,\n [WS_DATA_NAME]: toJson(data)\n },\n [TIMESTAMP_PARAM_NAME]: ts \n })\n}\n\n// extended function \nexport const createReplyMsg = (resolverName, data, ts = []) => (\n createWsReply(EMIT_REPLY_TYPE, resolverName, data, ts)\n)\n\nexport const createAcknowledgeMsg = (resolverName, data, ts = []) => (\n createWsReply(ACKNOWLEDGE_REPLY_TYPE, resolverName, data, ts)\n)\n\n/**\n * @param {string|object} payload should be string when reply but could be transformed\n * @return {boolean} true is OK\n */\nexport const isWsReply = payload => {\n const json = isString(payload) ? toJson(payload) : payload\n const { data } = json\n if (data) {\n let result = WS_KEYS.filter(key => isObjectHasKey(data, key))\n return (result.length === WS_KEYS.length) ? data : false\n }\n return false\n}\n\n/**\n * @param {string|object} data received data\n * @param {function} [cb=nil] this is for extracting the TS field or when it's error\n * @return {object} false on failed\n */\nexport const extractWsPayload = (payload, cb = nil) => {\n try {\n const json = toJson(payload)\n // now handle the data\n let _data\n if ((_data = isWsReply(json)) !== false) {\n // note the ts property is on its own \n cb(TIMESTAMP_PARAM_NAME, json[TIMESTAMP_PARAM_NAME])\n \n return {\n data: toJson(_data[WS_DATA_NAME]),\n resolverName: _data[WS_EVT_NAME],\n type: _data[WS_REPLY_TYPE]\n }\n }\n throw new JsonqlError(PAYLOAD_NOT_DECODED_ERR, payload)\n } catch(e) {\n return cb(ERROR_KEY, e)\n }\n}\n","// this will be part of the init client sequence\n// as soon as we create a ws client\n// we listen to the on.connect event \n// then we send a init-ping event back to the server\n// and server issue a csrf token back to use \n// we use this token to create a new client and destroy the old one\nimport {\n INTERCOM_RESOLVER_NAME, \n SOCKET_PING_EVENT_NAME,\n HEADERS_KEY,\n DATA_KEY,\n CSRF_HEADER_KEY\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n extractWsPayload,\n timestamp,\n toJson \n} from 'jsonql-utils/module'\nimport {\n JsonqlError\n} from 'jsonql-errors'\nconst CSRF_HEADER_NOT_EXIST_ERR = 'CSRF header is not in the received payload'\n\n/**\n * Util method \n * @param {string} payload return from server\n * @return {object} the useful bit \n */\nfunction extractSrvPayload(payload) {\n let json = toJson(payload)\n \n if (json && typeof json === 'object') {\n // note this method expect the json.data inside\n return extractWsPayload(json)\n }\n \n throw new JsonqlError('extractSrvPayload', json)\n}\n\n/**\n * call the server to get a csrf token \n * @return {string} formatted payload to send to the server \n */\nfunction createInitPing() {\n const ts = timestamp()\n\n return createQueryStr(INTERCOM_RESOLVER_NAME, [SOCKET_PING_EVENT_NAME, ts])\n}\n\n/**\n * Take the raw on.message result back then decoded it \n * @param {*} payload the raw result from server\n * @return {object} the csrf payload\n */\nfunction extractPingResult(payload) {\n const result = extractSrvPayload(payload)\n \n if (result && result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\n }\n }\n\n throw new JsonqlError('extractPingResult', CSRF_HEADER_NOT_EXIST_ERR)\n}\n\n\n/**\n * Create a generic intercom method\n * @param {string} type the event type \n * @param {array} args if any \n * @return {string} formatted payload to send\n */\nfunction createIntercomPayload(type, ...args) {\n const ts = timestamp()\n let payload = [type].concat(args)\n payload.push(ts)\n return createQueryStr(INTERCOM_RESOLVER_NAME, payload)\n}\n\n\nexport { \n extractSrvPayload,\n createInitPing, \n extractPingResult, \n createIntercomPayload \n}","// validator numbers\n// import { NUMBER_TYPES } from './constants';\n\nimport isNaN from 'lodash-es/isNaN'\nimport isString from 'lodash-es/isString'\n/**\n * @2015-05-04 found a problem if the value is a number like string\n * it will pass, so add a chck 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 trim from 'lodash-es/trim'\nimport isString from 'lodash-es/isString'\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\n\n/**\n * @param {boolean} value expected\n * @return {boolean} true if OK\n */\nconst checkIsBoolean = function(value) {\n return value !== null && value !== undefined && typeof value === 'boolean'\n}\n\nexport default checkIsBoolean\n","// validate any thing only check if there is something\n\nimport trim from 'lodash-es/trim'\n\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 (value !== undefined && value !== '' && trim(value) !== '') {\n if (checkNull === false || (checkNull === true && value !== null)) {\n return true;\n }\n }\n return false;\n}\n\nexport default checkIsAny\n","// Good practice rule - No magic number\n\nconst 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)`\nconst PARAMS_NOT_ARRAY_ERR = `params is not an array! Did something gone wrong when you generate the contract.json?`\nconst EXCEPTION_CASE_ERR = 'Could not understand your arguments and parameter structure!'\nconst UNUSUAL_CASE_ERR = 'This is an unusual situation where the arguments are more than the params, but not mark as spread'\n\nconst RETURNS_NAME = 'returns'\n\nimport {\n \n DEFAULT_TYPE, // this is a mistake should move back to the validation\n DATA_KEY, \n ERROR_KEY,\n\n TYPE_KEY,\n OPTIONAL_KEY,\n ENUM_KEY,\n ARGS_KEY,\n CHECKER_KEY,\n ALIAS_KEY,\n\n ARRAY_TYPE_LFT,\n ARRAY_TYPE_RGT,\n \n ARRAY_TYPE,\n OBJECT_TYPE,\n STRING_TYPE,\n BOOLEAN_TYPE,\n NUMBER_TYPE,\n KEY_WORD,\n OR_SEPERATOR\n} from 'jsonql-constants'\n\n// group all export in one \nexport {\n ARGS_NOT_ARRAY_ERR,\n PARAMS_NOT_ARRAY_ERR,\n EXCEPTION_CASE_ERR,\n UNUSUAL_CASE_ERR,\n DEFAULT_TYPE,\n ARRAY_TYPE_LFT,\n ARRAY_TYPE_RGT,\n TYPE_KEY,\n OPTIONAL_KEY,\n ENUM_KEY,\n ARGS_KEY,\n CHECKER_KEY,\n ALIAS_KEY,\n ARRAY_TYPE,\n OBJECT_TYPE,\n STRING_TYPE,\n BOOLEAN_TYPE,\n NUMBER_TYPE,\n KEY_WORD,\n OR_SEPERATOR,\n\n RETURNS_NAME,\n\n DATA_KEY, \n ERROR_KEY \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\n\nimport isArray from 'lodash-es/isArray'\nimport trim from 'lodash-es/trim'\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\n\nimport isPlainObject from 'lodash-es/isPlainObject'\n// import filter from 'lodash-es/filter'\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 (_value !== undefined) {\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 Reflect.apply(checkIsObject, null, _args)\n}\n","// move the index.js code here that make more sense to find where things are\n\nimport {\n checkIsArray,\n isArrayLike,\n arrayTypeHandler,\n objectTypeHandler,\n combineFn,\n notEmpty\n} from './index'\n\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 DATA_KEY, \n ERROR_KEY \n} from './constants'\n\n\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\nimport JsonqlError from 'jsonql-errors/src/error'\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 (arg !== undefined) {\n return arg\n }\n return (param.optional === true && param.defaultvalue !== undefined ? 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 JsonqlValidationError(PARAMS_NOT_ARRAY_ERR)\n }\n if (params.length === 0) {\n return []\n }\n if (!checkIsArray(args)) {\n throw new JsonqlValidationError(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:\n let ctn = params.length;\n // this happens when we have those array. type\n let _type = [ DEFAULT_TYPE ]\n // we only looking at the first one, this might be a @BUG\n /*\n if ((tmp = isArrayLike(params[0].type[0])) !== false) {\n _type = tmp;\n } */\n // if we use the params as guide then the rest will get throw out\n // which is not what we want, instead, anything without the param\n // will get a any type and optional flag\n return args.map((arg, i) => {\n let optional = i >= ctn ? true : !!params[i].optional\n let param = params[i] || { type: _type, name: `_${i}` }\n return {\n arg: optional ? getOptionalValue(arg, param) : arg,\n index: i,\n param,\n optional\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 // v1.4.4 this fixed the problem, the root level optional is from the last fn\n if (p.optional === true || 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","/** 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 * 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 * 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","/**\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","/** 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 * 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 * @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 from 'lodash-es/isFunction'\nimport merge from 'lodash-es/merge'\nimport mapValues from 'lodash-es/mapValues'\n\nimport JsonqlEnumError from 'jsonql-errors/src/enum-error'\nimport JsonqlTypeError from 'jsonql-errors/src/type-error'\nimport JsonqlCheckerError from 'jsonql-errors/src/checker-error'\n\nimport {\n TYPE_KEY,\n OPTIONAL_KEY,\n ENUM_KEY,\n ARGS_KEY,\n CHECKER_KEY,\n KEY_WORD\n} from '../constants'\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 // log('runValidationAction', key, value)\n throw new JsonqlTypeError(key, check)\n }\n if (value[ENUM_KEY] !== false && !enumHandler(value[ARGS_KEY], value[ENUM_KEY])) {\n // log(ENUM_KEY, value[ENUM_KEY])\n throw new JsonqlEnumError(key)\n }\n if (value[CHECKER_KEY] !== false && !checkerHandler(value[ARGS_KEY], value[CHECKER_KEY])) {\n // log(CHECKER_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\n\nimport merge from 'lodash-es/merge'\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 => runValidation(args1, cb))\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\n\nimport isFunction from 'lodash-es/isFunction'\nimport isString from 'lodash-es/isString'\nimport {\n ARGS_KEY,\n TYPE_KEY,\n CHECKER_KEY,\n ENUM_KEY,\n OPTIONAL_KEY,\n ALIAS_KEY\n} from 'jsonql-constants'\n\nimport { checkIsArray } from '../array'\n// import checkIsBoolean from '../boolean'\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 constructConfig(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/**\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 * construct the actual end user method, rename with prefix get since 1.5.2\n * @param {function} validateSync validation method\n * @return {function} for performaning the actual valdiation\n */\nconst getCheckConfigAsync = function(validateSync) {\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 */\n return function(config, appProps, constantProps= {}) {\n return checkOptionsAsync(config, appProps, constantProps, validateSync)\n }\n}\n\n/**\n * copy of above but it's sync, rename with prefix get since 1.5.2\n * @param {function} validateSync validation method\n * @return {function} for performaning the actual valdiation\n */\nconst getCheckConfig = 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 getCheckConfigAsync,\n getCheckConfig,\n JSONQL_PARAMS_VALIDATOR_INFO\n}\n","// export\nimport {\n checkIsObject,\n notEmpty,\n checkIsAny,\n checkIsString,\n checkIsBoolean,\n checkIsNumber,\n checkIsArray\n} from './src'\nimport * as validator from './src/validator'\n// configuration checking\nimport * as jsonqlOptions from './src/options'\n// the two extra functions\nimport isInArray from './src/is-in-array'\nimport isObjectHasKeyFn from './src/is-key-in-object'\n\nconst isObject = checkIsObject\nconst isAny = checkIsAny\nconst isString = checkIsString\nconst isBoolean = checkIsBoolean\nconst isNumber = checkIsNumber\nconst isArray = checkIsArray\nconst isNotEmpty = notEmpty\n\nconst normalizeArgs = validator.normalizeArgs\nconst validateSync = validator.validateSync\nconst validateAsync = validator.validateAsync\n\nconst JSONQL_PARAMS_VALIDATOR_INFO = jsonqlOptions.JSONQL_PARAMS_VALIDATOR_INFO\n\nconst createConfig = jsonqlOptions.createConfig\nconst constructConfig = jsonqlOptions.constructConfigFn\n// construct the final output 1.5.2\nconst checkConfigAsync = jsonqlOptions.getCheckConfigAsync(validator.validateSync)\nconst checkConfig = jsonqlOptions.getCheckConfig(validator.validateSync)\n\nconst inArray = isInArray\nconst isObjectHasKey = isObjectHasKeyFn\n\n// check returns methods \nimport { \n checkReturns, \n checkReturnsAsync, \n checkResolverReturns, \n checkResolverReturnsAsync \n} from './src/returns'\n\n\n// group the in one \nexport {\n JSONQL_PARAMS_VALIDATOR_INFO,\n \n isObject,\n isAny,\n isString,\n isBoolean,\n isNumber,\n isArray,\n isNotEmpty,\n \n inArray,\n isObjectHasKey,\n\n normalizeArgs,\n validateSync,\n validateAsync,\n\n createConfig,\n constructConfig,\n checkConfig,\n checkConfigAsync,\n\n checkReturns, \n checkReturnsAsync, \n checkResolverReturns, \n checkResolverReturnsAsync\n}\n\n\n\n\n\n","// move the get logger stuff here\n\n// it does nothing\nconst dummyLogger = () => {}\n\n/**\n * re-use the debugOn prop to control this log method\n * @param {object} opts configuration\n * @return {function} the log function\n */\nconst getLogger = (opts) => {\n const { debugOn } = opts \n if (debugOn) {\n return (...args) => {\n Reflect.apply(console.info, console, ['[jsonql-ws-client-core]', ...args])\n }\n }\n return dummyLogger\n}\n\n/**\n * Make sure there is a log method\n * @param {object} opts configuration\n * @return {object} opts\n */\nconst getLogFn = opts => {\n const { log } = opts // 1.3.9 if we pass a log method here then we use this\n if (!log || typeof log !== 'function') {\n return getLogger(opts)\n }\n opts.log('---> getLogFn user supplied log function <---', opts)\n return log\n}\n\nexport { getLogFn }","// group all the repetitive message here\n\nexport const TAKEN_BY_OTHER_TYPE_ERR = 'You are trying to register an event already been taken by other type:'\n","// Create two WeakMap store as a private keys\nexport const NB_EVENT_SERVICE_PRIVATE_STORE = new WeakMap()\nexport const NB_EVENT_SERVICE_PRIVATE_LAZY = new WeakMap()\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 function hashCode(s) {\n\treturn s.split(\"\").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0)\n}\n\n/**\n * wrapper to make sure it string\n * @param {*} input whatever\n * @return {string} output\n */\nexport function hashCode2Str(s) {\n return hashCode(s) + ''\n}\n\n/**\n * Just check if a pattern is an RegExp object\n * @param {*} pat whatever\n * @return {boolean} false when its not\n */\nexport function isRegExp(pat) {\n return pat instanceof RegExp\n}\n\n/**\n * check if its string\n * @param {*} arg whatever\n * @return {boolean} false when it's not\n */\nexport function isString(arg) {\n return typeof arg === 'string'\n}\n\n/**\n * Find from the array by matching the pattern\n * @param {*} pattern a string or RegExp object\n * @return {object} regex object or false when we can not id the input\n */\nexport function getRegex(pattern) {\n switch (true) {\n case isRegExp(pattern) === true:\n return pattern\n case isString(pattern) === true:\n return new RegExp(pattern)\n default:\n return false\n }\n}\n","// making all the functionality on it's own\n// import { WatchClass } from './watch'\n/*\nwe use a different way to do the same watch thing now\nthis.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*/\nimport { getRegex, isRegExp } from './utils'\n\nexport default class SuspendClass {\n\n constructor() {\n // suspend, release and queue\n this.__suspend_state__ = null\n // to do this proper we don't use a new prop to hold the event name pattern\n this.__pattern__ = null\n this.queueStore = new Set()\n }\n\n /**\n * start suspend\n * @return {void}\n */\n $suspend() {\n this.logger(`---> SUSPEND ALL OPS <---`)\n this.__suspend__(true)\n }\n\n /**\n * release the queue\n * @return {void}\n */\n $release() {\n this.logger(`---> RELEASE SUSPENDED QUEUE <---`)\n this.__suspend__(false)\n }\n\n /**\n * suspend event by pattern\n * @param {string} pattern the pattern search matches the event name\n * @return {void}\n */\n $suspendEvent(pattern) {\n const regex = getRegex(pattern)\n if (isRegExp(regex)) {\n this.__pattern__ = regex\n return this.$suspend()\n }\n throw new Error(`We expect a pattern variable to be string or RegExp, but we got \"${typeof regex}\" instead`)\n }\n\n /**\n * queuing call up when it's in suspend mode\n * @param {string} evt the event name\n * @param {*} args unknown number of arguments\n * @return {boolean} true when added or false when it's not\n */\n $queue(evt, ...args) {\n this.logger('($queue) get called')\n if (this.__suspend_state__ === true) {\n if (isRegExp(this.__pattern__)) { // it's better then check if its not null\n // check the pattern and decide if we want to suspend it or not\n let found = this.__pattern__.test(evt)\n if (!found) {\n return false\n }\n }\n this.logger('($queue) added to $queue', args)\n // @TODO there shouldn't be any duplicate, but how to make sure?\n this.queueStore.add([evt].concat(args))\n // return this.queueStore.size\n }\n return !!this.__suspend_state__\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 * to set the suspend and check if it's boolean value\n * @param {boolean} value to trigger\n */\n __suspend__(value) {\n if (typeof value === 'boolean') {\n const lastValue = this.__suspend_state__\n this.__suspend_state__ = value\n this.logger(`($suspend) Change from \"${lastValue}\" --> \"${value}\"`)\n if (lastValue === true && value === false) {\n this.__release__()\n }\n } else {\n throw new Error(`$suspend only accept Boolean value! we got ${typeof value}`)\n }\n }\n\n /**\n * Release the queue\n * @return {int} size if any\n */\n __release__() {\n let size = this.queueStore.size\n let pattern = this.__pattern__\n this.__pattern__ = null\n this.logger(`(release) was called with ${size}${pattern ? ' for \"' + pattern + '\"': ''} item${size > 1 ? 's' : ''}`)\n if (size > 0) {\n const queue = Array.from(this.queueStore)\n this.queueStore.clear()\n this.logger('(release 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 return size\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 { hashCode2Str, isString } from './utils'\nimport SuspendClass from './suspend'\n\nexport default class StoreService 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 (!isString(e)) {\n this.logger('(validateEvt)', e)\n throw new Error(`Event name must be string type! we got ${typeof e}`)\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! we got ${typeof callback}`)\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 this.validateEvt(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:', callback, 'payload:', payload, 'context:', 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 * This was part of the $get. We take it out\n * so we could use a regex to remove more than one event\n * @param {object} store the store to return from\n * @param {string} evt event name\n * @param {boolean} full return just the callback or everything\n * @return {array|boolean} false when not found\n */\n findFromStore(evt, store, full = false) {\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 * Similar to the findFromStore, but remove\n * @param {string} evt event name\n * @param {object} store the store to remove from\n * @return {boolean} false when not found\n */\n removeFromStore(evt, store) {\n if (store.has(evt)) {\n this.logger('($off)', evt)\n store.delete(evt)\n return true\n }\n return false\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(li => {\n let [hash,] = li\n return hash === args[0]\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(li => {\n let [,,t] = li\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) try to add \"${type}\" --> \"${evt}\" 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}\" --> \"${evt}\" can add to 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 this.logger(`(addToLazyStore) size: ${size}`)\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 hashCode2Str(fn.toString())\n }\n}\n","// The top level\nimport { TAKEN_BY_OTHER_TYPE_ERR } from './constants'\nimport StoreService from './store-service'\n// export\nexport default class EventService extends StoreService {\n /**\n * class constructor\n */\n constructor(config = {}) {\n super(config)\n }\n\n /**\n * logger function for overwrite\n */\n logger() {}\n\n // for id if the instance is this class\n get $name() {\n return 'to1source-event'\n }\n\n // take this down in the next release\n get is() {\n return this.$name\n }\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}\" 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 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(`${TAKEN_BY_OTHER_TYPE_ERR} ${t}`)\n }\n this.logger(`($on)`, `call run \"${evt}\"`)\n this.run(callback, payload, context || ctx)\n size += this.addToNormalStore(evt, type, callback, context || ctx)\n })\n\n this.logger(`($on) return size ${size}`)\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}\" is 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(`${TAKEN_BY_OTHER_TYPE_ERR} ${t}`)\n }\n this.logger('($once)', `call run \"${evt}\"`)\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 normalStore`)\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( li => {\n const [ payload, ctx, t ] = li\n if (t && t !== type) {\n throw new Error(`${TAKEN_BY_OTHER_TYPE_ERR} ${t}`)\n }\n this.logger(`($only) call run \"${evt}\"`)\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 added 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 normalStore`)\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(`${TAKEN_BY_OTHER_TYPE_ERR} ${t}`)\n }\n this.logger(`($onlyOnce) call run \"${evt}\"`)\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 this.logger(`($replace)`, evt, callback)\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 this.logger(`($trigger) \"${evt}\" found`)\n // @1.8.0 to add the suspend queue\n let added = this.$queue(evt, payload, context, type)\n if (added) {\n this.logger(`($trigger) Currently suspended \"${evt}\" added to queue, nothing executed. Exit now.`)\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.logger(`($trigger) call run for ${evt}`)\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 aroun\n * @NOTE breaking change: v1.9.1 it return an function to accept the params as spread\n * @param {string} evt event name\n * @param {string} type of call\n * @param {object} context what context callback execute in\n * @return {*} from $trigger\n */\n $call(evt, type = false, context = null) {\n const ctx = this\n\n return (...args) => {\n let _args = [evt, args, context, type]\n return Reflect.apply(ctx.$trigger, ctx, _args)\n }\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 // @TODO we will allow a regex pattern to mass remove event\n this.validateEvt(evt)\n let stores = [ this.lazyStore, this.normalStore ]\n\n return !!stores\n .filter(store => store.has(evt))\n .map(store => this.removeFromStore(evt, store))\n .length\n }\n\n /**\n * return all the listener bind to that event name\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 // @TODO should we allow the same Regex to search for all?\n this.validateEvt(evt)\n let store = this.normalStore\n return this.findFromStore(evt, store, full)\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) set 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 this.logger('($done) get result:', this.result)\n if (this.keep) {\n return this.result[this.result.length - 1]\n }\n return this.result\n }\n\n /**\n * Take a look inside the stores\n * @param {number|null} idx of the store, null means all\n * @return {void}\n */\n $debug(idx = null) {\n let names = ['lazyStore', 'normalStore']\n let stores = [this.lazyStore, this.normalStore]\n if (stores[idx]) {\n this.logger(names[idx], stores[idx])\n } else {\n stores.map((store, i) => {\n this.logger(names[i], store)\n })\n }\n }\n}\n","// default\nimport To1sourceEvent from './src/event-service'\n\nexport default To1sourceEvent\n","// this will generate a event emitter and will be use everywhere\nimport EventEmitterClass from '@to1source/event'\n// create a clone version so we know which one we actually is using\nclass JsonqlWsEvt extends EventEmitterClass {\n\n constructor(logger) {\n if (typeof logger !== 'function') {\n throw new Error(`Just die here the logger is not a function!`)\n }\n logger(`---> Create a new EventEmitter <---`)\n // this ee will always come with the logger\n // because we should take the ee from the configuration\n super({ logger })\n }\n\n get name() {\n return'jsonql-ws-client-core'\n }\n}\n\n/**\n * getting the event emitter\n * @param {object} opts configuration\n * @return {object} the event emitter instance\n */\nconst getEventEmitter = opts => {\n const { log, eventEmitter } = opts\n \n if (eventEmitter) {\n log(`eventEmitter is:`, eventEmitter.name)\n return eventEmitter\n }\n \n return new JsonqlWsEvt( opts.log )\n}\n\nexport { \n getEventEmitter, \n EventEmitterClass // for other module to build from \n}\n","// group all the small functions here\nimport { EMIT_REPLY_TYPE } from 'jsonql-constants'\nimport { toArray, createEvt } from 'jsonql-utils/src/generic'\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\n\n\n/**\n * WebSocket is strict about the path, therefore we need to make sure before it goes in\n * @param {string} url input url\n * @return {string} url with correct path name\n */\nexport const fixWss = url => {\n const uri = url.toLowerCase()\n if (uri.indexOf('http') > -1) {\n if (uri.indexOf('https') > -1) {\n return uri.replace('https', 'wss')\n }\n return uri.replace('http', 'ws')\n }\n return uri\n}\n\n\n/**\n * get a stock host name from browser\n */\nexport const getHostName = () => {\n try {\n return [window.location.protocol, window.location.host].join('//')\n } catch(e) {\n throw new JsonqlValidationError(e)\n }\n}\n\n/**\n * Unbind the event\n * @param {object} ee EventEmitter\n * @param {string} namespace\n * @return {void}\n */\nexport const clearMainEmitEvt = (ee, namespace) => {\n let nsps = toArray(namespace)\n nsps.forEach(n => {\n ee.$off(createEvt(n, EMIT_REPLY_TYPE))\n })\n}\n\n\n","// constants\n\nimport {\n EMIT_REPLY_TYPE,\n JS_WS_SOCKET_IO_NAME,\n JS_WS_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_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\nconst CB_FN_NAME = 'on'\n// this is a socket only (for now) feature so we just put it here \nconst DISCONNECTED_ERROR_MSG = `You have disconnected from the socket server, please reconnect.`\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 ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n NAMESPACE_KEY,\n UNKNOWN_RESULT,\n NOT_ALLOW_OP,\n MY_NAMESPACE,\n CB_FN_NAME,\n DISCONNECTED_ERROR_MSG\n}\n","// breaking it up further to share between methods\nimport { DATA_KEY, ERROR_KEY } from 'jsonql-constants'\nimport { UNKNOWN_RESULT } from '../options/constants'\nimport { isObjectHasKey } from '../utils'\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 NOT from promise\n * @param {function} rejecter NOT from promise\n * @return {void} nothing\n */\nexport function respondHandler(data, resolver, rejecter) {\n if (isObjectHasKey(data, ERROR_KEY)) {\n // debugFn('-- rejecter called --', data[ERROR_KEY])\n rejecter(data[ERROR_KEY])\n } else if (isObjectHasKey(data, DATA_KEY)) {\n // debugFn('-- resolver called --', data[DATA_KEY])\n // @NOTE we change from calling it directly to use reflect \n // this could have another problem later when the return data is no in an array structure\n Reflect.apply(resolver, null, [...data[DATA_KEY]])\n } else {\n // debugFn('-- UNKNOWN_RESULT --', data)\n rejecter({message: UNKNOWN_RESULT, error: data})\n }\n}\n","// the actual trigger call method\nimport { ON_RESULT_FN_NAME, EMIT_REPLY_TYPE } from 'jsonql-constants'\nimport { createEvt, toArray } from '../utils'\nimport { respondHandler } from './respond-handler'\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 * @param {function} log function \n * @return {void} nothing\n */\nexport function actionCall(ee, namespace, resolverName, args = [], log) {\n // reply event \n const outEventName = createEvt(namespace, EMIT_REPLY_TYPE)\n\n log(`actionCall: ${outEventName} --> ${resolverName}`, args)\n // This is the out going call \n ee.$trigger(outEventName, [resolverName, toArray(args)])\n \n // then we need to listen to the event callback here as well\n return new Promise((resolver, rejecter) => {\n const inEventName = createEvt(namespace, resolverName, ON_RESULT_FN_NAME)\n // this cause the onResult got the result back first \n // and it should be the promise resolve first\n // @TODO we need to rewrote the respondHandler to change the problem stated above \n ee.$on(\n inEventName,\n function actionCallResultHandler(result) {\n log(`got the first result`, result)\n respondHandler(result, resolver, rejecter)\n }\n )\n })\n}\n","// setting up the send method \nimport { JsonqlValidationError } from 'jsonql-errors'\nimport {\n ON_ERROR_FN_NAME,\n SEND_MSG_FN_NAME\n} from 'jsonql-constants'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { objDefineProps, createEvt, toArray, nil } from '../utils'\nimport { actionCall } from './action-call'\n\n/** \n * pairing with the server vesrion SEND_MSG_FN_NAME\n * last of the chain so only return the resolver (fn)\n * This is now change to a getter / setter method \n * and call like this: resolver.send(...args)\n * @param {function} fn the resolver function \n * @param {object} ee event emitter instance \n * @param {string} namespace the namespace it belongs to \n * @param {string} resolverName name of the resolver \n * @param {object} params from contract \n * @param {function} log a logger function\n * @return {function} return the resolver itself \n */ \nexport const setupSendMethod = (fn, ee, namespace, resolverName, params, log) => (\n objDefineProps(\n fn, \n SEND_MSG_FN_NAME, \n nil, \n function sendHandler() {\n log(`running call getter method`)\n // let _log = (...args) => Reflect.apply(console.info, console, ['[SEND]'].concat(args))\n /** \n * This will follow the same pattern like the resolver \n * @param {array} args list of unknown argument follow the resolver \n * @return {promise} resolve the result \n */\n return function sendCallback(...args) {\n return validateAsync(args, params.params, true)\n .then(_args => {\n // @TODO check the result \n // because the validation could failed with the list of fail properties \n log('execute send', namespace, resolverName, _args)\n return actionCall(ee, namespace, resolverName, _args, log)\n })\n .catch(err => {\n // @TODO it shouldn't be just a validation error \n // it could be server return error, so we need to check \n // what error we got back here first \n log('send error', err)\n // @TODO it might not an validation error need the finalCatch here\n ee.$call(\n createEvt(namespace, resolverName, ON_ERROR_FN_NAME),\n [new JsonqlValidationError(resolverName, err)]\n )\n })\n } \n })\n)\n","// break up the original setup resolver method here\n// import { JsonqlValidationError, finalCatch } from 'jsonql-errors'\nimport {\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME\n} from 'jsonql-constants'\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { actionCall } from './action-call'\n// local\nimport { MY_NAMESPACE } from '../options/constants'\nimport { chainFns, objDefineProps, injectToFn, createEvt, isFunc } from '../utils'\nimport { respondHandler } from './respond-handler'\nimport { setupSendMethod } from './setup-send-method'\n\n\n/**\n * moved back from generator-methods \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 * @param {function} log pass the log function\n * @return {function} resolver\n */\nfunction createResolver(ee, namespace, resolverName, params, log) {\n // note we pass the new withResult=true option\n return function resolver(...args) {\n return validateAsync(args, params.params, true)\n .then(_args => actionCall(ee, namespace, resolverName, _args, log))\n .catch(finalCatch)\n }\n}\n\n\n\n/**\n * The first one in the chain, just setup a namespace prop\n * the rest are passing through\n * @param {function} fn the resolver function\n * @param {object} ee the event emitter\n * @param {string} resolverName what it said\n * @param {object} params for resolver from contract\n * @param {function} log the logger function\n * @return {array}\n */\nconst setupNamespace = (fn, ee, namespace, resolverName, params, log) => [\n injectToFn(fn, MY_NAMESPACE, namespace),\n ee,\n namespace,\n resolverName,\n params,\n log\n]\n\n/**\n * onResult handler\n */\nconst setupOnResult = (fn, ee, namespace, resolverName, params, log) => [\n objDefineProps(fn, ON_RESULT_FN_NAME, function(resultCallback) {\n if (isFunc(resultCallback)) {\n ee.$on(\n createEvt(namespace, resolverName, ON_RESULT_FN_NAME),\n function resultHandler(result) {\n respondHandler(result, resultCallback, (error) => {\n log(`Catch error: \"${resolverName}\"`, error)\n ee.$trigger(\n createEvt(namespace, resolverName, ON_ERROR_FN_NAME),\n error\n )\n })\n }\n )\n }\n }),\n ee,\n namespace,\n resolverName,\n params,\n log\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 */\nconst setupOnMessage = (fn, ee, namespace, resolverName, params, log) => [\n objDefineProps(fn, ON_MESSAGE_FN_NAME, function(messageCallback) {\n // we expect this to be a function\n if (isFunc(messageCallback)) {\n // did that add to the callback\n let onMessageCallback = (args) => {\n log(`onMessageCallback`, args)\n respondHandler(\n args, \n messageCallback, \n (error) => {\n log(`Catch error: \"${resolverName}\"`, error)\n ee.$trigger(\n createEvt(namespace, resolverName, ON_ERROR_FN_NAME),\n error\n )\n })\n }\n // register the handler for this message event\n ee.$only(\n createEvt(namespace, resolverName, ON_MESSAGE_FN_NAME),\n onMessageCallback\n )\n }\n }),\n ee,\n namespace,\n resolverName,\n params,\n log\n]\n\n/**\n * ON_ERROR_FN_NAME handler\n */\nconst setupOnError = (fn, ee, namespace, resolverName, params, log) => [\n objDefineProps(fn, ON_ERROR_FN_NAME, function(resolverErrorHandler) {\n if (isFunc(resolverErrorHandler)) {\n // please note ON_ERROR_FN_NAME can add multiple listners\n ee.$only(\n createEvt(namespace, resolverName, ON_ERROR_FN_NAME),\n resolverErrorHandler\n )\n }\n }),\n ee,\n namespace,\n resolverName,\n params,\n log\n]\n\n/**\n * Add extra property / listeners 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 * @param {function} log function\n * @return {function} resolver\n */ \nfunction setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace,\n setupOnResult,\n setupOnMessage,\n setupOnError,\n setupSendMethod\n ]\n const executor = Reflect.apply(chainFns, null, fns)\n // get the executor\n return executor(fn, ee, namespace, resolverName, params, log)\n}\n\nexport { \n createResolver, \n setupResolver \n}","// put all the resolver related methods here to make it more clear\n\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\n\nimport { \n createResolver, \n setupResolver \n} from './setup-resolver'\nimport {\n injectToFn\n} from '../utils'\n\n\n/**\n * step one get the clientmap with the namespace\n * @param {object} opts configuration\n * @param {object} ee EventEmitter\n * @param {object} nspGroup resolvers index by their namespace\n * @return {promise} resolve the clientmapped, and start the chain\n */\nexport function generateResolvers(opts, ee, nspGroup) {\n const { log } = opts\n let client= {}\n \n for (let namespace in nspGroup) {\n let list = nspGroup[namespace]\n for (let resolverName in list) {\n // resolverNames.push(resolverName)\n let params = list[resolverName]\n let fn = createResolver(ee, namespace, resolverName, params, log)\n // this should set as a getter therefore can not be overwrite by accident\n client = injectToFn(\n client,\n resolverName,\n setupResolver(namespace, resolverName, params, fn, ee, log)\n )\n }\n }\n \n // resolve the clientto start the chain\n // chain the result to allow the chain processing\n return [ client, opts, ee, nspGroup ]\n}\n\n","// move from generator-methods \n// they are global event listeners \nimport {\n createEvt,\n objDefineProps,\n isFunc\n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * This event will fire when the socket.io.on('connection') and ws.onopen\n * @param {object} client client itself\n * @param {object} opts configuration\n * @param {object} ee Event Emitter\n * @return {array} [ obj, opts, ee ]\n */\nexport function setupOnReadyListener(client, opts, ee) {\n return [\n objDefineProps(\n client,\n ON_READY_FN_NAME,\n function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n // @2020-03-19 only allow ONE onReady callback otherwise\n // it will get fire multiple times which is not what we want\n ee.$only(ON_READY_FN_NAME, onReadyCallback)\n }\n }\n ),\n opts,\n ee\n ]\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} clientthe client itself\n * @param {object} opts configuration\n * @param {object} ee Event Emitter\n * @param {object} nspGroup namespace keys\n * @return {array} [obj, opts, ee]\n */\nexport function setupNamespaceErrorListener(client, opts, ee, nspGroup) {\n return [\n objDefineProps(\n client,\n ON_ERROR_FN_NAME,\n function namespaceErrorCallbackHandler(namespaceErrorHandler) {\n if (isFunc(namespaceErrorHandler)) {\n // please note ON_ERROR_FN_NAME can add multiple listners\n for (let namespace in nspGroup) {\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, ON_ERROR_FN_NAME), namespaceErrorHandler)\n }\n }\n }\n ),\n opts,\n ee\n ]\n}\n\n","// take out from the resolver-methods\nimport {\n LOGIN_EVENT_NAME,\n LOGOUT_EVENT_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { JsonqlValidationError } from 'jsonql-errors'\nimport { injectToFn, chainFns, isString, objDefineProps, isFunc } from '../utils'\n\n\n/**\n * @UPDATE it might be better if we decoup the two http-client only emit a login event\n * Here should catch it and reload the ws client @TBC\n * break out from createAuthMethods to allow chaining call\n * @param {object} obj the main client object\n * @param {object} opts configuration\n * @param {object} ee event emitter\n * @return {array} [ obj, opts, ee ] what comes in what goes out\n */\nconst setupLoginHandler = (obj, opts, ee) => [\n injectToFn(obj, opts.loginHandlerName, function loginHandler(token) {\n if (token && isString(token)) {\n opts.log(`Received ${LOGIN_EVENT_NAME} with ${token}`)\n // @TODO add the interceptor hook\n return ee.$trigger(LOGIN_EVENT_NAME, [token])\n }\n // should trigger a global error instead @TODO\n throw new JsonqlValidationError(opts.loginHandlerName, `Unexpected token ${token}`)\n }),\n opts,\n ee\n]\n\n\n/**\n * break out from createAuthMethods to allow chaining call - final in chain\n * @param {object} obj the main client object\n * @param {object} opts configuration\n * @param {object} ee event emitter\n * @return {array} [ obj, opts, ee ] what comes in what goes out\n */\nconst setupLogoutHandler = (obj, opts, ee) => [\n injectToFn(obj, opts.logoutHandlerName, function logoutHandler(...args) {\n ee.$trigger(LOGOUT_EVENT_NAME, args)\n }),\n opts,\n ee\n]\n\n\n/**\n * This event will fire when the socket.io.on('connection') and ws.onopen\n * Plus this will check if it's the private namespace that fired the event\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @return {array} [ obj, opts, ee] what comes in what goes out\n */\nconst setupOnLoginhandler = (obj, opts, ee) => [\n objDefineProps(obj, ON_LOGIN_FN_NAME, function onLoginCallbackHandler(onLoginCallback) {\n if (isFunc(onLoginCallback)) {\n // only one callback can registered with it, TBC\n // Should this be a $onlyOnce listener after the logout \n // we add it back? \n ee.$only(ON_LOGIN_FN_NAME, onLoginCallback)\n }\n }),\n opts,\n ee\n]\n\n// @TODO future feature setup switch user\n\n\n/**\n * Create auth related methods\n * @param {object} obj the client itself\n * @param {object} opts configuration\n * @param {object} ee Event Emitter\n * @return {array} [ obj, opts, ee ] what comes in what goes out\n */\nexport function setupAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler,\n setupLogoutHandler,\n setupOnLoginhandler\n )(obj, opts, ee)\n}\n","// this is a new method that will create several\n// intercom method also reverse listen to the server\n// such as disconnect (server issue disconnect)\nimport { injectToFn, chainFns } from '../utils'\nimport { \n CONNECT_EVENT_NAME,\n CONNECTED_EVENT_NAME,\n DISCONNECT_EVENT_NAME,\n CONNECTED_PROP_KEY\n} from 'jsonql-constants'\n\n/**\n * Set up the CONNECTED_PROP_KEY to the client\n * @param {*} client \n * @param {*} opts \n * @param {*} ee \n */\nfunction setupConnectPropKey(client, opts, ee) {\n const { log } = opts \n log('[1] setupConnectPropKey')\n // we just inject a helloWorld method here\n // set up the init state of the connect\n client = injectToFn(client, CONNECTED_PROP_KEY , false, true)\n return [ client, opts, ee ]\n}\n\n\n/**\n * setup listener to the connect event \n * @param {*} client \n * @param {*} opts \n * @param {*} ee \n */\nfunction setupConnectEvtListener(client, opts, ee) {\n // @TODO do what at this point?\n const { log } = opts \n\n log(`[2] setupConnectEvtListener`)\n\n ee.$on(CONNECT_EVENT_NAME, function(...args) {\n log(`setupConnectEvtListener pass and do nothing at the moment`, args)\n })\n \n return [client, opts, ee]\n}\n\n/**\n * setup listener to the connected event \n * @param {*} client \n * @param {*} opts \n * @param {*} ee \n */\nfunction setupConnectedEvtListener(client, opts, ee) {\n const { log } = opts \n\n log(`[3] setupConnectedEvtListener`)\n\n ee.$on(CONNECTED_EVENT_NAME, function() {\n client[CONNECTED_PROP_KEY] = true\n log(`CONNECTED_EVENT_NAME`, true)\n\n return {[CONNECTED_PROP_KEY]: true}\n })\n\n return [client, opts, ee]\n}\n\n/**\n * Listen to the disconnect event and set the property to the client \n * @param {*} client \n * @param {*} opts \n * @param {*} ee \n */\nfunction setupDisconnectListener(client, opts, ee) {\n const { log } = opts \n\n log(`[4] setupDisconnectListener`)\n\n ee.$on(DISCONNECT_EVENT_NAME, function() {\n client[CONNECTED_PROP_KEY] = false\n log(`CONNECTED_EVENT_NAME`, false)\n\n return {[CONNECTED_PROP_KEY]: false}\n })\n\n return [client, opts, ee]\n}\n\n/**\n * disconnect action\n * @param {*} client \n * @param {*} opts \n * @param {*} ee \n * @return {object} this is the final step to return the client\n */\nfunction setupDisconectAction(client, opts, ee) {\n const { disconnectHandlerName, log } = opts\n log(`[5] setupDisconectAction`)\n\n return injectToFn(\n client,\n disconnectHandlerName,\n function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n }\n )\n}\n\n/**\n * this is the new method that setup the intercom handler\n * also this serve as the final call in the then chain to\n * output the client\n * @param {object} client the client\n * @param {object} opts configuration\n * @param {object} ee the event emitter\n * @return {object} client\n */\nexport function setupInterCom(client, opts, ee) {\n const fns = [\n setupConnectPropKey,\n setupConnectEvtListener,\n setupConnectedEvtListener,\n setupDisconnectListener,\n setupDisconectAction\n ]\n\n const executor = Reflect.apply(chainFns, null, fns)\n return executor(client, opts, ee)\n}\n","// The final step of the setup before it returns the client\nimport { setupInterCom } from './setup-intercom'\nimport { CONNECT_EVENT_NAME } from 'jsonql-constants'\n\n/**\n * The final step to return the client\n * @param {object} obj the client\n * @param {object} opts configuration\n * @param {object} ee the event emitter\n * @return {object} client\n */\nfunction setupFinalStep(obj, opts, ee) {\n \n let client = setupInterCom(obj, opts, ee)\n // opts.log(`---> The final step to return the ws-client <---`)\n // add some debug functions\n client.verifyEventEmitter = () => ee.is\n // we add back the two things into the client\n // then when we do integration, we run it in reverse,\n // create the ws client first then the host client\n client.eventEmitter = opts.eventEmitter\n client.log = opts.log\n\n // now at this point, we are going to call the connect event\n ee.$trigger(CONNECT_EVENT_NAME, [opts, ee]) // just passing back the entire opts object\n \n return client\n}\n\n\nexport { setupFinalStep }\n","// resolvers generator\n// we change the interface to return promise from v1.0.3\n// this way we make sure the obj return is correct and timely\nimport { NSP_GROUP } from 'jsonql-constants'\nimport { chainFns } from '../utils'\n\nimport { generateResolvers } from './generator-methods'\nimport {\n setupOnReadyListener,\n setupNamespaceErrorListener\n} from './global-listener'\n\nimport { setupAuthMethods } from './setup-auth-methods'\n\nimport { setupFinalStep } from './setup-final-step'\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 function callersGenerator(opts, nspMap, ee) {\n let fns = [\n generateResolvers,\n setupOnReadyListener,\n setupNamespaceErrorListener\n ]\n if (opts.enableAuth) {\n // there is a problem here, when this is a public namespace\n // it should not have a login logout event attach to it\n fns.push(setupAuthMethods)\n }\n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n // This has move outside of here, into the main method\n // the reason is we could switch around the sequence much easier\n fns.push(setupFinalStep)\n // stupid reaon!!!\n const executer = Reflect.apply(chainFns, null, fns)\n // run it\n return executer(opts, ee, nspMap[NSP_GROUP])\n}\n","// create options\nimport {\n checkConfigAsync,\n checkConfig\n} from 'jsonql-params-validator'\nimport {\n wsCoreCheckMap,\n wsCoreConstProps,\n socketCheckMap\n} from './defaults'\nimport {\n fixWss,\n getHostName,\n getEventEmitter,\n getNspInfoByConfig,\n getLogFn\n} from '../utils'\n\n/**\n * We need this to find the socket server type\n * @param {*} config\n * @return {string} the name of the socket server if any\n */\nfunction checkSocketClientType(config) {\n return checkConfig(config, socketCheckMap)\n}\n\n/**\n * Create a combine checkConfig for the creating the combine client\n * @param {*} configCheckMap\n * @param {*} constProps\n * @return {function} takes the user input config then resolve the configuration\n */\nfunction createCombineConfigCheck(configCheckMap, constProps) {\n const combineCheckMap = Object.assign({}, configCheckMap, wsCoreCheckMap)\n const combineConstProps = Object.assign({}, constProps, wsCoreConstProps)\n return config => checkConfigAsync(config, combineCheckMap, combineConstProps)\n}\n\n\n/**\n * wrapper method to check this already did the pre check\n * @param {object} config user supply config\n * @param {object} defaultOptions for checking\n * @param {object} constProps user supply const props\n * @return {promise} resolve to the checked opitons\n */\nfunction checkConfiguration(config, defaultOptions, constProps) {\n const defaultCheckMap= Object.assign(wsCoreCheckMap, defaultOptions)\n const wsConstProps = Object.assign(wsCoreConstProps, constProps)\n\n return checkConfigAsync(config, defaultCheckMap, wsConstProps)\n}\n\n/**\n * Taking the `then` part from the method below\n * @param {object} opts\n * @return {promise} opts all done\n */\nfunction postCheckInjectOpts(opts) {\n return Promise.resolve(opts)\n .then(opts => {\n if (!opts.hostname) {\n opts.hostname = getHostName()\n }\n // @TODO the contract now will supply the namespace information\n // and we need to use that to group the namespace call\n opts.wssPath = fixWss([opts.hostname, opts.namespace].join('/'), opts.serverType)\n // get the log function here\n opts.log = getLogFn(opts)\n\n opts.eventEmitter = getEventEmitter(opts)\n\n return opts\n })\n}\n\n/**\n * Don't want to make things confusing\n * Breaking up the opts process in one place\n * then generate the necessary parameter in another step\n * @2020-3-20 here we suspend operation by it's namespace first\n * Then in the framework part, after the connection establish we release\n * the queue\n * @param {object} opts checked --> merge --> injected\n * @return {object} {opts, nspMap, ee}\n */\nfunction createRequiredParams(opts) {\n const nspMap = getNspInfoByConfig(opts)\n const ee = opts.eventEmitter\n // @TODO here we are going to add suspend event to the namespace related methods\n \n return { opts, nspMap, ee }\n}\n\nexport {\n // properties\n wsCoreCheckMap,\n wsCoreConstProps,\n // functions\n checkConfiguration,\n postCheckInjectOpts,\n createRequiredParams,\n // this will just get export for integration\n checkSocketClientType,\n createCombineConfigCheck\n}\n","// the top level API\n// The goal is to create a generic method that will able to handle\n// any kind of clients\n// import { injectToFn } from 'jsonql-utils'\nimport { callersGenerator } from './callers'\nimport {\n checkConfiguration,\n postCheckInjectOpts,\n createRequiredParams\n} from './options'\n\n\n/**\n * 0.5.0 we break up the wsClientCore in two parts one without the config check\n * @param {function} setupSocketClientListener just make sure what it said it does\n * @return {function} to actually generate the client\n */\nexport function wsClientCoreAction(setupSocketClientListener) {\n /**\n * This is a breaking change, to continue the onion skin design\n * @param {object} config the already checked config\n * @return {promise} resolve the client\n */\n return function createClientAction(config = {}) {\n\n return postCheckInjectOpts(config)\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => setupSocketClientListener(opts, nspMap, ee, 'jsonql-ws-client-core')\n )\n .then(\n ({opts, nspMap, ee}) => callersGenerator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`[jsonql-ws-core-client init error]`, err)\n })\n }\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} socketClientListerner this is the one method export by various clients\n * @param {object} [configCheckMap={}] we should do all the checking in the core instead of the client\n * @param {object} [constProps={}] add this to supply the constProps from the downstream client\n * @return {function} accept a config then return the wsClient instance with all the available API\n */\nexport function wsClientCore(socketClientListener, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(\n wsClientCoreAction(socketClientListener)\n )\n}\n","// this is getting too confusing \n// therefore we move it back to the framework specific \n\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 */\nfunction createNspClient(namespace, opts) {\n const { hostname, wssPath, wsOptions, nspClient, log } = opts\n const url = namespace ? [hostname, namespace].join('/') : wssPath\n log(`createNspClient --> `, url)\n\n return 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 */\nfunction createNspAuthClient(namespace, opts) {\n const { hostname, wssPath, token, wsOptions, nspAuthClient, log } = opts\n const url = namespace ? [hostname, namespace].join('/') : wssPath\n \n log(`createNspAuthClient -->`, url)\n\n if (token && typeof token !== 'string') {\n throw new Error(`Expect token to be string, but got ${token}`)\n }\n \n return nspAuthClient(url, token, wsOptions)\n}\n\nexport {\n createNspClient,\n createNspAuthClient\n}\n","// this use by client-event-handler\nimport { ON_ERROR_FN_NAME } from 'jsonql-constants'\nimport { createEvt } from '../utils'\n\n/**\n * trigger errors on all the namespace onError handler\n * @param {object} ee Event Emitter\n * @param {array} namespaces nsps string\n * @param {string} message optional\n * @return {void}\n */\nexport function triggerNamespacesOnError(ee, namespaces, message) {\n namespaces.forEach( namespace => {\n ee.$trigger(\n createEvt(namespace, ON_ERROR_FN_NAME), \n [{ message, namespace }]\n )\n })\n}\n\n/**\n * Handle the onerror callback \n * @param {object} ee event emitter \n * @param {string} namespace which namespace has error \n * @param {*} err error object\n * @return {void} \n */\nexport const handleNamespaceOnError = (ee, namespace, err) => {\n ee.$trigger(createEvt(namespace, ON_ERROR_FN_NAME), [err])\n}","// NOT IN USE AT THE MOMENT JUST KEEP IT HERE FOR THE TIME BEING \nimport {\n LOGOUT_EVENT_NAME,\n NOT_LOGIN_ERR_MSG,\n ON_ERROR_FN_NAME,\n ON_RESULT_FN_NAME,\n DISCONNECT_EVENT_NAME\n} from 'jsonql-constants'\nimport { EMIT_EVT, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * Only when there is a private namespace then we bind to this event\n * @param {object} nsps the available nsp(s)\n * @param {array} namespaces available namespace \n * @param {object} ee eventEmitter \n * @param {object} opts configuration\n * @return {void}\n */\nexport const logoutEvtListener = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n // this will be available regardless enableAuth\n // because the server can log the client out\n ee.$on(\n LOGOUT_EVENT_NAME, \n function logoutEvtCallback() {\n const privateNamespace = getPrivateNamespace(namespaces)\n log(`${LOGOUT_EVENT_NAME} event triggered`)\n // disconnect(nsps, opts.serverType)\n // we need to issue error to all the namespace onError Listerner\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the Listerner to the fake one\n log(`logout from ${privateNamespace}`)\n\n clearMainEmitEvt(ee, privateNamespace)\n // we need to issue one more call to the server before we disconnect\n // now this is a catch 22, here we are not suppose to do anything platform specific\n // so that should fire before trigger this event\n // clear out the nsp\n nsps[privateNamespace] = null \n // add a NOT LOGIN error if call\n notLoginWsListerner(privateNamespace, ee, opts)\n }\n )\n}\n\n/**\n * A Event Listerner placeholder when it's not connect to any nsp\n * @param {string} namespace nsp\n * @param {object} ee EventEmitter\n * @param {object} opts configuration\n * @return {void}\n */\nexport const notConnectedListener = (namespace, ee, opts) => {\n const { log } = opts \n\n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedEvtCallback(resolverName, args) {\n log(`[disconnectedListerner] hijack the ws call`, namespace, resolverName, args)\n const error = {\n message: DISCONNECTED_ERROR_MSG\n }\n ee.$call(createEvt(namespace, resolverName, ON_ERROR_FN_NAME), [ error ])\n // also trigger the result Listerner, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n\n/**\n * The disconnect event Listerner, now we log the client out from everything\n * @TODO now we are another problem they disconnect, how to reconnect\n * @param {object} nsps the available nsp(s)\n * @param {array} namespaces available namespace \n * @param {object} ee eventEmitter \n * @param {object} opts configuration\n * @return {void}\n */\nexport const disconnectListener = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(\n DISCONNECT_EVENT_NAME, \n function disconnectEvtCallback() {\n triggerNamespacesOnError(ee, namespaces, DISCONNECT_EVENT_NAME)\n namespaces.forEach( namespace => { \n log(`disconnect from ${namespace}`)\n\n clearMainEmitEvt(ee, namespace)\n nsps[namespace] = null \n disconnectedListerner(namespace, ee, opts)\n })\n }\n )\n}\n\n/**\n * A Event Listerner placeholder when it's not connect to the private nsp\n * @param {string} namespace nsp\n * @param {object} ee EventEmitter\n * @param {object} opts configuration\n * @return {void}\n */\nexport const notLoginListener = (namespace, ee, opts) => {\n const { log } = opts \n\n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginListernerCallback(resolverName, args) {\n log('[notLoginListerner] hijack the ws call', namespace, resolverName, args)\n const error = { message: NOT_LOGIN_ERR_MSG }\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, ON_ERROR_FN_NAME), [ error ])\n // also trigger the result Listerner, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}","// This is share between different clients so we export it\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\n\n/*\nInside the map call but we take it out for now and until the WebSocket version is fully working\nimport { SOCKET_IO } from '../options/constants'\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n*/\nimport { getPrivateNamespace } from 'jsonql-utils/src/namespace'\nimport { logoutEvtListener, notLoginListener } from './event-listeners'\n\n/**\n * centralize all the comm in one place\n * @param {function} bindSocketEventHandler binding the ee to ws --> this is the core bit\n * @param {object} nsps namespaced nsp\n * @return {void} nothing\n */\nexport function namespaceEventListener(bindSocketEventListener, nsps) {\n /**\n * BREAKING CHANGE instead of one flat structure\n * we return a function to accept the two\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts\n * @param {object} ee Event Emitter instance\n * @return {array} although we return something but this is the last step and nothing to do further\n */\n return (opts, nspMap, ee) => {\n // since all these params already in the opts\n const { log } = opts\n const { namespaces } = nspMap\n // @1.1.3 add isPrivate prop to id which namespace is the private nsp\n // then we can use this prop to determine if we need to fire the ON_LOGIN_PROP_NAME event\n const privateNamespace = getPrivateNamespace(namespaces)\n\n return namespaces.map(namespace => {\n let isPrivate = privateNamespace === namespace\n log(namespace, ` --> ${isPrivate ? 'private': 'public'} nsp --> `, nsps[namespace] !== false)\n if (nsps[namespace]) {\n log('[call bindWsHandler]', isPrivate, namespace)\n\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // Finally we binding everything together\n Reflect.apply(bindSocketEventListener, null, args)\n\n } else {\n log(`binding notLoginWsHandler to ${namespace}`)\n // a dummy placeholder\n // @TODO but it should be a not connect handler\n // when it's not login (or fail) this should be handle differently\n notLoginListener(namespace, ee, opts)\n }\n if (isPrivate) {\n log(`Has private and add logoutEvtHandler`)\n logoutEvtListener(nsps, namespaces, ee, opts)\n }\n // just return something its not going to get use anywhere\n return isPrivate\n })\n }\n}\n","// jsonql-ws-core takes over the check configuration\n// here we only have to supply the options that is unique to this client\n// create options\nimport { JS_WS_NAME } from 'jsonql-constants'\n// constant props\nconst wsClientConstProps = {\n version: '__PLACEHOLDER__', // will get replace\n serverType: JS_WS_NAME\n}\n\nexport { wsClientConstProps }\n","// pass the different type of ws to generate the client\n// this is where the framework specific code get injected\nimport { TOKEN_PARAM_NAME } from 'jsonql-constants'\nimport { fixWss } from '../modules'\nimport {\n createInitPing, \n extractPingResult\n} from '../modules'\n\n/**\n * Group the ping and get respond create new client in one\n * @param {object} ws \n * @param {object} WebSocket \n * @param {string} url\n * @param {function} resolver \n * @param {function} rejecter \n * @param {boolean} auth client or not\n * @return {promise} resolve the confirm client\n */\nfunction initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) {\n // @TODO how to we id this client can issue a CSRF\n // by origin? \n ws.onopen = function onOpenCallback() {\n ws.send(createInitPing())\n }\n\n ws.onmessage = function onMessageCallback(payload) {\n try {\n const header = extractPingResult(payload.data)\n // @NOTE the break down test in ws-client-core show no problems\n // the problem was cause by malform nspInfo that time? \n setTimeout(() => { // delay or not show no different but just on the safe side\n ws.terminate()\n }, 50)\n const newWs = new WebSocket(url, Object.assign(wsOptions, header)) \n resolver(newWs) \n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\n }\n\n return ws // just return it\n}\n\n/**\n * less duplicated code the better \n * @param {object} WebSocket \n * @param {string} url formatted url\n * @param {object} options or not\n * @return {promise} resolve the actual verified client\n */\nfunction asyncConnect(WebSocket, url, options) {\n \n return new Promise((resolver, rejecter) => { \n const unconfirmClient = new WebSocket(url, options)\n \n return initPingAction(unconfirmClient, WebSocket, url, resolver, rejecter, options)\n })\n}\n\n\n/**\n * The bug was in the wsOptions where ws don't need it but socket.io do\n * therefore the object was pass as second parameter!\n * @NOTE here we only return a method to create the client, it might not get call \n * @param {object} WebSocket the client or node version of ws\n * @param {boolean} auth if it's auth then 3 param or just one\n * @param {object} opts this is a breaking change we will init the client twice\n */\nfunction initWebSocketClient(WebSocket, auth, log) {\n if (auth === false) {\n /**\n * Create a non-protected client\n * @param {string} url \n * @param {object} [wsOptions={}]\n * @return {promise} resolve to the confirmed client\n */\n return function createWsClient(url, wsOptions = {}) {\n const _url = fixWss(url)\n log(`nspClient: \\n${_url}\\n`, wsOptions)\n\n return asyncConnect(WebSocket, _url, wsOptions)\n }\n }\n\n /**\n * Create a client with auth token\n * @param {string} url start with ws:// @TODO check this?\n * @param {string} token the jwt token\n * @param {object} [wsOptions={}] extra options pass to the WebSocket object\n * @return {object} ws instance\n */\n return function createWsAuthClient(url, token, wsOptions = {}) {\n const ws_url = fixWss(url)\n // console.log('what happen here?', url, ws_url, token)\n const _url = token && typeof token === 'string' ? `${ws_url}?${TOKEN_PARAM_NAME}=${token}` : ws_url\n log(`nspAuthClient: \\n${_url}\\n`, wsOptions)\n\n return asyncConnect(WebSocket, _url, wsOptions)\n }\n}\n\nexport { initWebSocketClient }","// @BUG when call disconnected\n// this keep causing an \"Disconnect call failed TypeError: Cannot read property 'readyState' of null\"\n// I think that is because it's not login then it can not be disconnect\n// how do we track this state globally\nimport { \n LOGIN_EVENT_NAME, \n CONNECT_EVENT_NAME \n} from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * when we received a login event \n * from the http-client or the standalone login call \n * we received a token here --> update the opts then trigger \n * the CONNECT_EVENT_NAME again\n * @param {object} opts configurations\n * @param {object} nspMap contain all the required info\n * @param {object} ee event emitter\n * @return {void}\n */\nexport function loginEventListener(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n log(`[4] loginEventHandler`)\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n\n log('createClient LOGIN_EVENT_NAME $only handler')\n // clear out all the event binding\n clearMainEmitEvt(ee, namespaces)\n // reload the nsp and rebind all the events\n opts.token = tokenFromLoginAction \n ee.$trigger(CONNECT_EVENT_NAME, [opts, ee]) // don't need to pass the nspMap \n })\n}\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 * 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 * 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 * 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 * 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","/**\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 * 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","/** 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 * 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 * 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 * 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 * 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 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 * 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","/** 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","/**\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 * 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 `_.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","/** 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 * 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 * 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","/**\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 * 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","/** 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","// break it out on its own because\n// it's building from the lodash-es from scratch\n// according to this discussion https://github.com/lodash/lodash/issues/3298\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport merge from 'lodash-es/merge'\n\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 * @param {boolean} asObject if true then merge the result object\n * @return {object} promise resolved with the array of promises resolved results\n */\nexport function chainPromises(promises, asObject = false) {\n return promises.reduce((promiseChain, currentTask) => (\n promiseChain.then(chainResults => (\n currentTask.then(currentResult => (\n asObject === false ? [...chainResults, currentResult] : merge(chainResults, currentResult)\n ))\n ))\n ), Promise.resolve(\n asObject === false ? [] : (isPlainObject(asObject) ? asObject : {})\n ))\n}\n\n\n/**\n * This one return a different result from the chainPromises\n * it will be the same like chainFns that take one promise resolve as the next fn parameter\n * @param {function} initPromise a function that accept param and resolve result\n * @param {array} promises array of function pass that resolve promises\n * @return {promise} resolve the processed result\n */\nexport function chainProcessPromises(initPromise, ...promises) {\n return (...args) => (\n promises.reduce((promiseChain, currentTask) => (\n promiseChain.then(chainResult => (\n currentTask(chainResult)\n )\n )\n ), Reflect.apply(initPromise, null, args))\n )\n}\n","// actually binding the event client to the socket client\nimport {\n createNspClient,\n createNspAuthClient\n} from './modules'\nimport {\n chainPromises \n} from 'jsonql-utils/src/chain-promises'\n\n/**\n * Because the nsps can be throw away so it doesn't matter the scope\n * this will get reuse again\n * @NOTE when we enable the standalone method this sequence will not change \n * only call and reload\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 {promise} resolve the nsps namespace with namespace as key\n */\nconst createNsp = function(opts, nspMap, token = null) {\n // we leave the token param out because it could get call by another method\n token = token || opts.token \n let { publicNamespace, namespaces } = nspMap\n const { log } = opts \n log(`createNspAction`, 'publicNamespace', publicNamespace, 'namespaces', namespaces)\n \n // reverse the namespaces because it got stuck for some reason\n // const reverseNamespaces = namespaces.reverse()\n if (opts.enableAuth) {\n return chainPromises(\n namespaces.map((namespace, i) => {\n if (i === 0) {\n if (token) {\n opts.token = token\n log('create createNspAuthClient at run time')\n return createNspAuthClient(namespace, opts)\n }\n return Promise.resolve(false)\n }\n return createNspClient(namespace, opts)\n })\n )\n .then(results => \n results.map((result, i) => \n ({ [namespaces[i]]: result }))\n .reduce((a, b) => Object.assign(a, b), {})\n )\n }\n\n return createNspClient(false, opts)\n .then(nsp => ({[publicNamespace]: nsp}))\n}\n\nexport { createNsp }\n","// bunch of generic helpers\n\nimport isArray from 'lodash-es/isArray'\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport trim from 'lodash-es/trim'\n\n/**\n * DIY in Array\n * @param {array} arr to check from\n * @param {*} value to check against\n * @return {boolean} true on found\n */\nexport const inArray = (arr, value) => !!arr.filter(a => a === value).length\n\n// quick and dirty to turn non array to array\nexport const toArray = (arg) => isArray(arg) ? arg : [arg]\n\n/**\n * parse string to json or just return the original value if error happened\n * @param {*} n input\n * @param {boolean} [t=true] or throw\n * @return {*} json object on success\n */\nexport const parseJson = function(n, t=true) {\n try {\n return JSON.parse(n)\n } catch(e) {\n if (t) {\n return n\n }\n throw new Error(e)\n }\n}\n\n/**\n * @param {object} obj for search\n * @param {string} key target\n * @return {boolean} true on success\n */\nexport const isObjectHasKey = function(obj, key) {\n try {\n const keys = Object.keys(obj)\n return inArray(keys, key)\n } catch(e) {\n // @BUG when the obj is not an OBJECT we got some weird output\n return false\n }\n}\n\n/**\n * create a event name\n * @param {string[]} args\n * @return {string} event name for use\n */\nexport const createEvt = (...args) => args.join('_')\n\n/**\n * simple util method to get the value\n * @param {string} name of the key\n * @param {object} obj to take value from\n * @return {*} the object value id by name or undefined\n */\nexport const getConfigValue = (name, obj) => (\n obj && isPlainObject(obj) ? ( (name in obj) ? obj[name] : undefined ) : undefined\n)\n\n/**\n * small util to make sure the return value is valid JSON object\n * @param {*} n input\n * @return {object} correct JSON object\n */\nexport const toJson = n => {\n if (typeof n === 'string') {\n return parseJson(n)\n }\n return parseJson(JSON.stringify(n))\n}\n\n/**\n * Check several parameter that there is something in the param\n * @param {*} param input\n * @return {boolean}\n */\nexport const isNotEmpty = function(param) {\n return param !== undefined && param !== false && param !== null && trim(param) !== ''\n}\n\n/**\n * Simple check if the prop is function\n * @param {*} prop input\n * @return {boolean} true on success\n */\nexport const isFunc = prop => {\n if (typeof prop === 'function') {\n return true;\n }\n console.error(`Expect to be Function type! Got ${typeof prop}`)\n}\n\n/**\n * Shorthand method for Object.assign \n * @param {array} args \n * @return {object} merge together object by key \n */\nexport const assign = (...args) => Reflect.apply(Object.assign, Object, args)\n \n/** \n * generic placeholder function\n * @return {boolean} false \n */\nexport const nil = () => false\n\n/**\n * generic turn config into immutatble \n */\nexport const freeze = config => Object.freeze(config)","// 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","/**\n * @param {boolean} sec return in second or not\n * @return {number} timestamp\n */\nexport const timestamp = (sec = false) => {\n let time = Date.now()\n return sec ? Math.floor( time / 1000 ) : time\n}\n","// ported from jsonql-params-validator\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 TIMESTAMP_PARAM_NAME\n} from 'jsonql-constants'\n\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\n\nimport isArray from 'lodash-es/isArray'\nimport isString from 'lodash-es/isString'\nimport isPlainObject from 'lodash-es/isPlainObject'\n\nimport { timestamp } from './timestamp'\nimport { parseJson } from './generic'\n\n/**\n * check if the payload has a timestamp field, then append a new timestamp to it\n * @param {object} payload from the com\n * @return {array} timestamp field with an array value\n */\nexport const handleTimestamp = payload => {\n let ts = payload[TIMESTAMP_PARAM_NAME]\n if (!isArray(ts)) {\n ts = [ts]\n }\n ts.push( timestamp() )\n\n return ts\n}\n\n/**\n * make sure it's an object (it was call formatPayload but it doesn't make sense)\n * @param {*} payload the object comes in could be string based\n * @return {object} the transformed payload\n */\nexport const toPayload = payload => isString(payload) ? parseJson(payload) : payload\n\n/**\n * @param {*} args arguments to send\n *@return {object} formatted payload\n */\nexport const formatPayload = (args) => (\n { [QUERY_ARG_NAME]: args }\n)\n\n/**\n * extract the resolver name from the payload \n * @param {object} payload\n * @return {string} resolver name \n */\nexport function getResolverFromPayload(payload) {\n const keys = Object.keys(payload)\n return keys.filter(key => key !== TIMESTAMP_PARAM_NAME)[0]\n}\n\n/**\n * wrapper method to add the timestamp as well\n * @param {string} resolverName\n * @param {*} payload\n * @return {object} delierable\n */\nexport function createDeliverable(resolverName, payload) {\n return {\n [resolverName]: payload,\n [TIMESTAMP_PARAM_NAME]: [ timestamp() ]\n }\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) && isArray(args)) {\n let payload = formatPayload(args)\n if (jsonp === true) {\n return payload\n }\n return createDeliverable(resolverName, payload)\n }\n throw new JsonqlValidationError(`[createQuery] expect resolverName to be string and args to be array!`, { resolverName, args })\n}\n\n/**\n * string version of the createQuery\n * @return {string}\n */\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 createDeliverable(resolverName, _payload)\n }\n throw new JsonqlValidationError(`[createMutation] expect resolverName to be string!`, { resolverName, payload, condition })\n}\n\n/**\n * string version of createMutation\n * @return {string}\n */\nexport function createMutationStr(resolverName, payload, condition = {}, jsonp = false) {\n return JSON.stringify(createMutation(resolverName, payload, condition, jsonp))\n}\n\n/**\n * Extract the parts from payload and format for use\n * @param {string} resolverName name of fn\n * @param {object} payload the incoming json\n * @return {object|boolean} false on failed\n */\nexport function getQueryFromArgs(resolverName, payload) {\n if (resolverName && isPlainObject(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 [TIMESTAMP_PARAM_NAME]: handleTimestamp(payload)\n }\n }\n }\n return false\n}\n\n/**\n * Share function so no repeat\n * @param {object} payload the payload from client\n * @param {function} processor the last get result method\n * @return {*} result processed result\n */\nfunction processPayload(payload, processor) {\n const p = toPayload(payload)\n const resolverName = getResolverFromPayload(p)\n return Reflect.apply(processor, null, [resolverName, p])\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 result = processPayload(payload, getQueryFromArgs)\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 && isPlainObject(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 [TIMESTAMP_PARAM_NAME]: handleTimestamp(payload)\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 result = processPayload(payload, getMutationFromArgs)\n\n if (result !== false) {\n return result\n }\n throw new JsonqlValidationError('[getMutationArgs] Payload is malformed!', payload)\n}\n","// There are the socket related methods ported back from \n// ws-server-core and ws-client-core \nimport {\n WS_REPLY_TYPE,\n WS_EVT_NAME,\n WS_DATA_NAME,\n TIMESTAMP_PARAM_NAME,\n ERROR_KEY,\n EMIT_REPLY_TYPE,\n ACKNOWLEDGE_REPLY_TYPE\n} from 'jsonql-constants'\nimport { JsonqlError } from 'jsonql-errors' \nimport isString from 'lodash-es/isString'\n\nimport { toJson, isObjectHasKey, nil } from './generic'\nimport { timestamp } from './timestamp'\n\nconst PAYLOAD_NOT_DECODED_ERR = 'payload can not decoded'\nconst WS_KEYS = [\n WS_REPLY_TYPE,\n WS_EVT_NAME,\n WS_DATA_NAME\n]\n\n/////////////////////////////////////\n// REPLY FROM SERVER //\n/////////////////////////////////////\n\n\n/**\n * The ws doesn't have a acknowledge callback like socket.io\n * so we have to DIY one for ws and other that doesn't have it\n * @param {string} type of reply\n * @param {string} resolverName which is replying\n * @param {*} data payload\n * @param {array} [ts= []] the last received ts, if any \n * @return {string} stringify json\n */\nexport const createWsReply = (type, resolverName, data, ts = []) => {\n ts.push(timestamp())\n return JSON.stringify({\n data: {\n [WS_REPLY_TYPE]: type,\n [WS_EVT_NAME]: resolverName,\n [WS_DATA_NAME]: toJson(data)\n },\n [TIMESTAMP_PARAM_NAME]: ts \n })\n}\n\n// extended function \nexport const createReplyMsg = (resolverName, data, ts = []) => (\n createWsReply(EMIT_REPLY_TYPE, resolverName, data, ts)\n)\n\nexport const createAcknowledgeMsg = (resolverName, data, ts = []) => (\n createWsReply(ACKNOWLEDGE_REPLY_TYPE, resolverName, data, ts)\n)\n\n/**\n * @param {string|object} payload should be string when reply but could be transformed\n * @return {boolean} true is OK\n */\nexport const isWsReply = payload => {\n const json = isString(payload) ? toJson(payload) : payload\n const { data } = json\n if (data) {\n let result = WS_KEYS.filter(key => isObjectHasKey(data, key))\n return (result.length === WS_KEYS.length) ? data : false\n }\n return false\n}\n\n/**\n * @param {string|object} data received data\n * @param {function} [cb=nil] this is for extracting the TS field or when it's error\n * @return {object} false on failed\n */\nexport const extractWsPayload = (payload, cb = nil) => {\n try {\n const json = toJson(payload)\n // now handle the data\n let _data\n if ((_data = isWsReply(json)) !== false) {\n // note the ts property is on its own \n cb(TIMESTAMP_PARAM_NAME, json[TIMESTAMP_PARAM_NAME])\n \n return {\n data: toJson(_data[WS_DATA_NAME]),\n resolverName: _data[WS_EVT_NAME],\n type: _data[WS_REPLY_TYPE]\n }\n }\n throw new JsonqlError(PAYLOAD_NOT_DECODED_ERR, payload)\n } catch(e) {\n return cb(ERROR_KEY, e)\n }\n}\n","// taken out from the bind-socket-event-handler \nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\nimport { createIntercomPayload } from '../modules'\n\n/**\n * This is the actual logout (terminate socket connection) handler \n * There is another one that is handle what should do when this happen \n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nexport function disconnectEventListener(ee, ws) {\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(DISCONNECT_EVENT_NAME, function closeEvtHandler() {\n try {\n // @TODO we need find a way to get the userdata\n ws.send(createIntercomPayload(LOGOUT_EVENT_NAME))\n log('terminate ws connection')\n ws.terminate()\n } catch(e) {\n console.error('ws.terminate error', e)\n }\n })\n}","// the WebSocket main handler\nimport {\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME,\n ON_ERROR_FN_NAME\n} from 'jsonql-constants'\nimport {\n createQueryStr,\n createEvt,\n extractWsPayload\n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError\n} from '../modules'\nimport { \n disconnectEventListener\n} from './disconnect-event-listener'\n\n/**\n * in some edge case 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 * @return {undefined} nothing return\n */\nexport const errorTypeHandler = (ee, namespace, resolverName, json) => {\n let evt = [namespace]\n if (resolverName) {\n evt.push(resolverName)\n }\n evt.push(ON_ERROR_FN_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 event to socket normally\n * @param {string} namespace\n * @param {object} ws the nsp\n * @param {object} ee EventEmitter\n * @param {boolean} isPrivate to id if this namespace is private or not\n * @param {object} opts configuration\n * @return {object} promise resolve after the onopen event\n */\nexport function bindSocketEventHandler(namespace, ws, ee, isPrivate, opts) {\n const { log } = opts\n let onReadCalls = 2\n // setup the logut event listener \n // this will hear the event and actually call the ws.terminate\n if (isPrivate) {\n log('Private namespace', namespace, ' binding to the DISCONNECT ws.terminate')\n disconnectEventListener(ee, ws)\n }\n // log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n\n log('=== ws.onopen listened -->', namespace)\n // we just call the onReady\n ee.$trigger(ON_READY_FN_NAME, [namespace])\n // we only want to allow it get call twice (number of namespaces)\n --onReadCalls\n if (onReadCalls === 0) {\n ee.$off(ON_READY_FN_NAME)\n }\n\n // need an extra parameter here to id the private nsp\n if (isPrivate) {\n log(`isPrivate and fire the ${ON_LOGIN_FN_NAME}`)\n ee.$call(ON_LOGIN_FN_NAME)(namespace)\n }\n // add listener only after the open is called\n ee.$only(\n createEvt(namespace, EMIT_REPLY_TYPE),\n /**\n * actually send the payload to server\n * @param {string} resolverName\n * @param {array} args NEED TO CHECK HOW WE PASS THIS!\n */\n function wsMainOnEvtHandler(resolverName, args) {\n const payload = createQueryStr(resolverName, args)\n log('ws.onopen.send', resolverName, args, payload)\n\n ws.send(payload)\n }\n )\n }\n\n // reply\n // If we change it to the event callback style\n // then the payload will just be the payload and fucks up the extractWsPayload call @TODO\n ws.onmessage = function onMessageCallback(payload) {\n log(`ws.onmessage raw payload`, payload.data)\n \n // console.log(`on.message`, typeof payload, payload)\n try {\n // log(`ws.onmessage raw payload`, payload)\n // @TODO the payload actually contain quite a few things - is that changed?\n // type: message, data: data_send_from_server\n const json = extractWsPayload(payload.data)\n const { resolverName, type } = json\n\n log('Respond from server', type, json)\n\n switch (type) {\n case EMIT_REPLY_TYPE:\n let e1 = createEvt(namespace, resolverName, ON_MESSAGE_FN_NAME)\n let r = ee.$call(e1)(json)\n \n log(`EMIT_REPLY_TYPE`, e1, r)\n break\n case ACKNOWLEDGE_REPLY_TYPE:\n let e2 = createEvt(namespace, resolverName, ON_RESULT_FN_NAME)\n let x2 = ee.$call(e2)(json)\n\n log(`ACKNOWLEDGE_REPLY_TYPE`, e2, x2)\n break\n case ERROR_KEY:\n // this is handled error and we won't throw it\n // we need to extract the error from json\n log(`ERROR_KEY`)\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 log('Unhandled event!', json)\n errorTypeHandler(ee, namespace, resolverName, json)\n // let error = {error: {'message': 'Unhandled event!', type}};\n // ee.$trigger(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [error])\n }\n } catch(e) {\n log(`ws.onmessage error`, e)\n errorTypeHandler(ee, namespace, false, e)\n }\n }\n // when the server close the connection\n ws.onclose = function onCloseCallback() {\n log('ws.onclose callback')\n // @TODO what to do with this\n // ee.$trigger(LOGOUT_EVENT_NAME, [namespace])\n }\n // add a onerror event handler here\n ws.onerror = function onErrorCallback(err) {\n // trigger a global error event\n log(`ws.onerror`, err)\n handleNamespaceOnError(ee, namespace, err)\n }\n \n // we don't bind the logut here and just return the ws \n return ws \n}\n","// take out from the bind-framework-to-jsonql \nimport { CONNECT_EVENT_NAME } from 'jsonql-constants'\nimport { namespaceEventListener } from '../modules'\nimport { createNsp } from '../create-nsp'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * This is the hard of establishing the connection and binding to the jsonql events \n * @param {*} nspMap \n * @param {*} ee event emitter\n * @param {function} log function to show internal \n * @return {void}\n */\nexport function connectEventListener(nspMap, ee, log) {\n log(`[2] setup the CONNECT_EVENT_NAME`)\n // this is a automatic trigger from within the framework\n ee.$only(CONNECT_EVENT_NAME, function connectEventNameHandler($config, $ee) {\n log(`[3] CONNECT_EVENT_NAME`, $ee)\n\n return createNsp($config, nspMap)\n .then(nsps => namespaceEventListener(bindSocketEventHandler, nsps))\n .then(listenerFn => listenerFn($config, nspMap, $ee))\n })\n\n // log(`[3] after setup the CONNECT_EVENT_NAME`)\n}","// share method to create the wsClientResolver\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\nimport { initWebSocketClient } from './init-websocket-client'\nimport { \n loginEventListener, \n connectEventListener \n} from '../listeners'\n\n/**\n * Create the framework <---> jsonql client binding\n * @param {object} frameworkModule the different WebSocket module\n * @return {function} the wsClientResolver\n */\nfunction bindFrameworkToJsonql(frameworkModule) {\n /**\n * wsClientResolver\n * @param {object} opts configuration\n * @param {object} nspMap from the contract\n * @param {object} ee instance of the eventEmitter\n * @param {string} msg a message to id where the data coming from\n * @return {object} passing the same 3 input out with additional in the opts\n */\n return function createClientBindingAction(opts, nspMap, ee, msg) {\n const { log } = opts\n\n log(`Where the parameters coming from:`, msg)\n\n opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log) \n // debug \n log(`[1] bindFrameworkToJsonql`, ee.name, nspMap)\n // @2020-03-20 @NOTE \n \n connectEventListener(nspMap, ee, log)\n \n // next we need to setup the login event handler\n // But the same design (see above) when we received a login event \n // from the http-client or the standalone login call \n // we received a token here --> update the opts then trigger \n // the CONNECT_EVENT_NAME again\n loginEventListener(opts, nspMap, ee)\n\n log(`just before returing the values for the next operation from createClientBindingAction`)\n\n // we just return what comes in\n return { opts, nspMap, ee }\n }\n}\n\nexport { bindFrameworkToJsonql }","// this will be the news style interface that will pass to the jsonql-ws-client\n// then return a function for accepting an opts to generate the final\n// client api\nimport WebSocket from 'ws'\nimport createWebSocketBinding from '../core/create-websocket-binding'\n\n/**\n * @param {object} opts configuration\n * @param {object} nspMap from the contract\n * @param {object} ee instance of the eventEmitter\n * @return {object} passing the same 3 input out with additional in the opts\n */\nexport default createWebSocketBinding(WebSocket)\n","// this is the module entry point for node client\nimport {\n wsClientCore\n} from './core/modules'\nimport { wsClientConstProps } from './options'\n\nimport setupSocketClientListener from './node/setup-socket-client-listener'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n \n return wsClientCore(\n setupSocketClientListener, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )(config)\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;ACAA;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;ACAA;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;ACAA;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;"}
\ No newline at end of file
+{"version":3,"file":"main.js","sources":["../../ws-client-core/node_modules/lodash-es/isArray.js","node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/lodash-es/_objectToString.js","../../ws-client-core/node_modules/lodash-es/_overArg.js","../../ws-client-core/node_modules/lodash-es/isObjectLike.js","../../ws-client-core/node_modules/lodash-es/_arrayMap.js","../../ws-client-core/node_modules/lodash-es/_baseSlice.js","../../ws-client-core/node_modules/lodash-es/_baseFindIndex.js","../../ws-client-core/node_modules/lodash-es/_baseIsNaN.js","../../ws-client-core/node_modules/lodash-es/_strictIndexOf.js","../../ws-client-core/node_modules/lodash-es/_asciiToArray.js","../../ws-client-core/node_modules/lodash-es/_hasUnicode.js","../../ws-client-core/node_modules/lodash-es/_unicodeToArray.js","../../ws-client-core/node_modules/jsonql-utils/src/generic.js","../../ws-client-core/node_modules/lodash-es/_listCacheClear.js","../../ws-client-core/node_modules/lodash-es/eq.js","../../ws-client-core/node_modules/lodash-es/_stackDelete.js","../../ws-client-core/node_modules/lodash-es/_stackGet.js","../../ws-client-core/node_modules/lodash-es/_stackHas.js","../../ws-client-core/node_modules/lodash-es/isObject.js","../../ws-client-core/node_modules/lodash-es/_toSource.js","../../ws-client-core/node_modules/lodash-es/_getValue.js","../../ws-client-core/node_modules/lodash-es/_hashDelete.js","../../ws-client-core/node_modules/lodash-es/_isKeyable.js","../../ws-client-core/node_modules/lodash-es/_createBaseFor.js","../../ws-client-core/node_modules/lodash-es/_copyArray.js","../../ws-client-core/node_modules/lodash-es/_isPrototype.js","../../ws-client-core/node_modules/lodash-es/isLength.js","../../ws-client-core/node_modules/lodash-es/stubFalse.js","../../ws-client-core/node_modules/lodash-es/_baseUnary.js","../../ws-client-core/node_modules/lodash-es/_safeGet.js","../../ws-client-core/node_modules/lodash-es/_baseTimes.js","../../ws-client-core/node_modules/lodash-es/_isIndex.js","../../ws-client-core/node_modules/lodash-es/_nativeKeysIn.js","../../ws-client-core/node_modules/lodash-es/identity.js","../../ws-client-core/node_modules/lodash-es/_apply.js","../../ws-client-core/node_modules/lodash-es/constant.js","../../ws-client-core/node_modules/lodash-es/_shortOut.js","../../ws-client-core/node_modules/jsonql-errors/src/enum-error.js","../../ws-client-core/node_modules/jsonql-errors/src/type-error.js","../../ws-client-core/node_modules/jsonql-errors/src/checker-error.js","../../ws-client-core/node_modules/jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/jsonql-utils/src/contract.js","../../ws-client-core/node_modules/jsonql-utils/src/timestamp.js","../../ws-client-core/node_modules/jsonql-utils/src/params-api.js","../../ws-client-core/node_modules/jsonql-utils/src/namespace.js","../../ws-client-core/node_modules/jsonql-utils/src/socket.js","../../ws-client-core/src/callers/intercom-methods.js","../../ws-client-core/node_modules/jsonql-params-validator/src/number.js","../../ws-client-core/node_modules/jsonql-params-validator/src/string.js","../../ws-client-core/node_modules/jsonql-params-validator/src/boolean.js","../../ws-client-core/node_modules/jsonql-params-validator/src/any.js","../../ws-client-core/node_modules/jsonql-params-validator/src/constants.js","../../ws-client-core/node_modules/jsonql-params-validator/src/combine.js","../../ws-client-core/node_modules/jsonql-params-validator/src/array.js","../../ws-client-core/node_modules/jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/jsonql-params-validator/src/validator.js","../../ws-client-core/node_modules/lodash-es/_setCacheAdd.js","../../ws-client-core/node_modules/lodash-es/_setCacheHas.js","../../ws-client-core/node_modules/lodash-es/_arraySome.js","../../ws-client-core/node_modules/lodash-es/_cacheHas.js","../../ws-client-core/node_modules/lodash-es/_mapToArray.js","../../ws-client-core/node_modules/lodash-es/_setToArray.js","../../ws-client-core/node_modules/lodash-es/_arrayPush.js","../../ws-client-core/node_modules/lodash-es/_arrayFilter.js","../../ws-client-core/node_modules/lodash-es/stubArray.js","../../ws-client-core/node_modules/lodash-es/_matchesStrictComparable.js","../../ws-client-core/node_modules/lodash-es/_baseHasIn.js","../../ws-client-core/node_modules/lodash-es/_baseProperty.js","../../ws-client-core/node_modules/lodash-es/negate.js","../../ws-client-core/node_modules/lodash-es/_baseFindKey.js","../../ws-client-core/node_modules/jsonql-params-validator/src/is-in-array.js","../../ws-client-core/node_modules/jsonql-params-validator/src/options/run-validation.js","../../ws-client-core/node_modules/jsonql-params-validator/src/options/check-options-async.js","../../ws-client-core/node_modules/jsonql-params-validator/src/options/construct-config.js","../../ws-client-core/node_modules/jsonql-params-validator/src/options/index.js","../../ws-client-core/node_modules/jsonql-params-validator/index.js","../../ws-client-core/src/utils/get-log-fn.js","../../ws-client-core/node_modules/@to1source/event/src/constants.js","../../ws-client-core/node_modules/@to1source/event/src/utils.js","../../ws-client-core/node_modules/@to1source/event/src/store.js","../../ws-client-core/node_modules/@to1source/event/src/base.js","../../ws-client-core/node_modules/@to1source/event/src/suspend.js","../../ws-client-core/node_modules/@to1source/event/src/store-service.js","../../ws-client-core/node_modules/@to1source/event/src/event-service.js","../../ws-client-core/node_modules/@to1source/event/index.js","../../ws-client-core/src/utils/get-event-emitter.js","../../ws-client-core/src/utils/helpers.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/callers/respond-handler.js","../../ws-client-core/src/callers/action-call.js","../../ws-client-core/src/callers/setup-send-method.js","../../ws-client-core/src/callers/setup-resolver.js","../../ws-client-core/src/callers/generator-methods.js","../../ws-client-core/src/callers/global-listener.js","../../ws-client-core/src/callers/setup-auth-methods.js","../../ws-client-core/src/callers/setup-intercom.js","../../ws-client-core/src/callers/setup-final-step.js","../../ws-client-core/src/callers/callers-generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/listener/create-nsp-clients.js","../../ws-client-core/src/listener/trigger-namespaces-on-error.js","../../ws-client-core/src/listener/event-listeners.js","../../ws-client-core/src/listener/namespace-event-listener.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.js","src/core/listeners/login-event-listener.js","node_modules/lodash-es/_objectToString.js","node_modules/lodash-es/_overArg.js","node_modules/lodash-es/isObjectLike.js","node_modules/lodash-es/_listCacheClear.js","node_modules/lodash-es/eq.js","node_modules/lodash-es/_stackDelete.js","node_modules/lodash-es/_stackGet.js","node_modules/lodash-es/_stackHas.js","node_modules/lodash-es/isObject.js","node_modules/lodash-es/_toSource.js","node_modules/lodash-es/_getValue.js","node_modules/lodash-es/_hashDelete.js","node_modules/lodash-es/_isKeyable.js","node_modules/lodash-es/_createBaseFor.js","node_modules/lodash-es/_copyArray.js","node_modules/lodash-es/_isPrototype.js","node_modules/lodash-es/isArray.js","node_modules/lodash-es/isLength.js","node_modules/lodash-es/stubFalse.js","node_modules/lodash-es/_baseUnary.js","node_modules/lodash-es/_safeGet.js","node_modules/lodash-es/_baseTimes.js","node_modules/lodash-es/_isIndex.js","node_modules/lodash-es/_nativeKeysIn.js","node_modules/lodash-es/identity.js","node_modules/lodash-es/_apply.js","node_modules/lodash-es/constant.js","node_modules/lodash-es/_shortOut.js","node_modules/jsonql-utils/src/chain-promises.js","src/core/create-nsp.js","node_modules/jsonql-utils/src/generic.js","node_modules/jsonql-errors/src/validation-error.js","node_modules/jsonql-utils/src/timestamp.js","node_modules/jsonql-utils/src/params-api.js","node_modules/jsonql-utils/src/socket.js","src/core/listeners/disconnect-event-listener.js","src/core/listeners/bind-socket-event-handler.js","src/core/listeners/connect-event-listener.js","src/core/create-websocket-binding/bind-websocket-to-jsonql.js","src/node/setup-socket-client-listener.js","src/node-ws-client.js"],"sourcesContent":["/**\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","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 * 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 * 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 * 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","/**\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","/**\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 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","/** 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","// bunch of generic helpers\n\nimport isArray from 'lodash-es/isArray'\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport trim from 'lodash-es/trim'\n\n/**\n * DIY in Array\n * @param {array} arr to check from\n * @param {*} value to check against\n * @return {boolean} true on found\n */\nexport const inArray = (arr, value) => !!arr.filter(a => a === value).length\n\n// quick and dirty to turn non array to array\nexport const toArray = (arg) => isArray(arg) ? arg : [arg]\n\n/**\n * parse string to json or just return the original value if error happened\n * @param {*} n input\n * @param {boolean} [t=true] or throw\n * @return {*} json object on success\n */\nexport const parseJson = function(n, t=true) {\n try {\n return JSON.parse(n)\n } catch(e) {\n if (t) {\n return n\n }\n throw new Error(e)\n }\n}\n\n/**\n * @param {object} obj for search\n * @param {string} key target\n * @return {boolean} true on success\n */\nexport const isObjectHasKey = function(obj, key) {\n try {\n const keys = Object.keys(obj)\n return inArray(keys, key)\n } catch(e) {\n // @BUG when the obj is not an OBJECT we got some weird output\n return false\n }\n}\n\n/**\n * create a event name\n * @param {string[]} args\n * @return {string} event name for use\n */\nexport const createEvt = (...args) => args.join('_')\n\n/**\n * simple util method to get the value\n * @param {string} name of the key\n * @param {object} obj to take value from\n * @return {*} the object value id by name or undefined\n */\nexport const getConfigValue = (name, obj) => (\n obj && isPlainObject(obj) ? ( (name in obj) ? obj[name] : undefined ) : undefined\n)\n\n/**\n * small util to make sure the return value is valid JSON object\n * @param {*} n input\n * @return {object} correct JSON object\n */\nexport const toJson = n => {\n if (typeof n === 'string') {\n return parseJson(n)\n }\n return parseJson(JSON.stringify(n))\n}\n\n/**\n * Check several parameter that there is something in the param\n * @param {*} param input\n * @return {boolean}\n */\nexport const isNotEmpty = function(param) {\n return param !== undefined && param !== false && param !== null && trim(param) !== ''\n}\n\n/**\n * Simple check if the prop is function\n * @param {*} prop input\n * @return {boolean} true on success\n */\nexport const isFunc = prop => {\n if (typeof prop === 'function') {\n return true;\n }\n console.error(`Expect to be Function type! Got ${typeof prop}`)\n}\n\n/**\n * Shorthand method for Object.assign \n * @param {array} args \n * @return {object} merge together object by key \n */\nexport const assign = (...args) => Reflect.apply(Object.assign, Object, args)\n \n/** \n * generic placeholder function\n * @return {boolean} false \n */\nexport const nil = () => false\n\n/**\n * generic turn config into immutatble \n */\nexport const freeze = config => Object.freeze(config)","/**\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 * 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","/**\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 * 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","/** 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 * 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 * 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 * 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 * 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 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","/** 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","/**\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 * 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 `_.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","/** 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 * 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 * 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","/**\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 * 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","/** 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","// 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","// split the contract into the node side and the generic side\nimport { isObjectHasKey } from './generic'\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport {\n QUERY_NAME,\n MUTATION_NAME,\n SOCKET_NAME,\n QUERY_ARG_NAME,\n PAYLOAD_PARAM_NAME,\n CONDITION_PARAM_NAME\n} from 'jsonql-constants'\nimport { JsonqlError, JsonqlResolverNotFoundError } from 'jsonql-errors'\n/**\n * Check if the json is a contract file or not\n * @param {object} contract json object\n * @return {boolean} true\n */\nexport function checkIsContract(contract) {\n return isPlainObject(contract)\n && (\n isObjectHasKey(contract, QUERY_NAME)\n || isObjectHasKey(contract, MUTATION_NAME)\n || isObjectHasKey(contract, SOCKET_NAME)\n )\n}\n\n/**\n * Wrapper method that check if it's contract then return the contract or false\n * @param {object} contract the object to check\n * @return {boolean | object} false when it's not\n */\nexport function isContract(contract) {\n return checkIsContract(contract) ? contract : false\n}\n\n/**\n * Ported from jsonql-params-validator but different\n * if we don't find the socket part then return false\n * @param {object} contract the contract object\n * @return {object|boolean} false on failed\n */\nexport function extractSocketPart(contract) {\n if (isObjectHasKey(contract, SOCKET_NAME)) {\n return contract[SOCKET_NAME]\n }\n return false\n}\n\n/**\n * Extract the args from the payload\n * @param {object} payload to work with\n * @param {string} type of call\n * @return {array} args\n */\nexport function extractArgsFromPayload(payload, type) {\n switch (type) {\n case QUERY_NAME:\n return payload[QUERY_ARG_NAME]\n case MUTATION_NAME:\n return [\n payload[PAYLOAD_PARAM_NAME],\n payload[CONDITION_PARAM_NAME]\n ]\n default:\n throw new JsonqlError(`Unknown ${type} to extract argument from!`)\n }\n}\n\n/**\n * Like what the name said\n * @param {object} contract the contract json\n * @param {string} type query|mutation\n * @param {string} name of the function\n * @return {object} the params part of the contract\n */\nexport function extractParamsFromContract(contract, type, name) {\n try {\n const result = contract[type][name]\n // debug('extractParamsFromContract', result)\n if (!result) {\n // debug(name, type, contract)\n throw new JsonqlResolverNotFoundError(name, type)\n }\n return result\n } catch(e) {\n throw new JsonqlResolverNotFoundError(name, e)\n }\n}\n","/**\n * @param {boolean} sec return in second or not\n * @return {number} timestamp\n */\nexport const timestamp = (sec = false) => {\n let time = Date.now()\n return sec ? Math.floor( time / 1000 ) : time\n}\n","// ported from jsonql-params-validator\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 TIMESTAMP_PARAM_NAME\n} from 'jsonql-constants'\n\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\n\nimport isArray from 'lodash-es/isArray'\nimport isString from 'lodash-es/isString'\nimport isPlainObject from 'lodash-es/isPlainObject'\n\nimport { timestamp } from './timestamp'\nimport { parseJson } from './generic'\n\n/**\n * check if the payload has a timestamp field, then append a new timestamp to it\n * @param {object} payload from the com\n * @return {array} timestamp field with an array value\n */\nexport const handleTimestamp = payload => {\n let ts = payload[TIMESTAMP_PARAM_NAME]\n if (!isArray(ts)) {\n ts = [ts]\n }\n ts.push( timestamp() )\n\n return ts\n}\n\n/**\n * make sure it's an object (it was call formatPayload but it doesn't make sense)\n * @param {*} payload the object comes in could be string based\n * @return {object} the transformed payload\n */\nexport const toPayload = payload => isString(payload) ? parseJson(payload) : payload\n\n/**\n * @param {*} args arguments to send\n *@return {object} formatted payload\n */\nexport const formatPayload = (args) => (\n { [QUERY_ARG_NAME]: args }\n)\n\n/**\n * extract the resolver name from the payload \n * @param {object} payload\n * @return {string} resolver name \n */\nexport function getResolverFromPayload(payload) {\n const keys = Object.keys(payload)\n return keys.filter(key => key !== TIMESTAMP_PARAM_NAME)[0]\n}\n\n/**\n * wrapper method to add the timestamp as well\n * @param {string} resolverName name of the resolver\n * @param {*} payload what is sending \n * @param {object} extra additonal property we want to merge into the deliverable\n * @return {object} delierable\n */\nexport function createDeliverable(resolverName, payload, extra = {}) {\n return Object.assign({\n [resolverName]: payload,\n [TIMESTAMP_PARAM_NAME]: [ timestamp() ]\n }, extra)\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) && isArray(args)) {\n let payload = formatPayload(args)\n if (jsonp === true) {\n return payload\n }\n return createDeliverable(resolverName, payload)\n }\n throw new JsonqlValidationError('utils:params-api:createQuery', { \n message: `expect resolverName to be string and args to be array!`,\n resolverName, \n args \n })\n}\n\n/**\n * string version of the createQuery\n * @return {string}\n */\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 createDeliverable(resolverName, _payload)\n }\n throw new JsonqlValidationError(`[createMutation] expect resolverName to be string!`, { resolverName, payload, condition })\n}\n\n/**\n * string version of createMutation\n * @return {string}\n */\nexport function createMutationStr(resolverName, payload, condition = {}, jsonp = false) {\n return JSON.stringify(createMutation(resolverName, payload, condition, jsonp))\n}\n\n/**\n * Extract the parts from payload and format for use\n * @param {string} resolverName name of fn\n * @param {object} payload the incoming json\n * @return {object|boolean} false on failed\n */\nexport function getQueryFromArgs(resolverName, payload) {\n if (resolverName && isPlainObject(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 [TIMESTAMP_PARAM_NAME]: handleTimestamp(payload)\n }\n }\n }\n return false\n}\n\n/**\n * Share function so no repeat\n * @param {object} payload the payload from client\n * @param {function} processor the last get result method\n * @return {*} result processed result\n */\nfunction processPayload(payload, processor) {\n const p = toPayload(payload)\n const resolverName = getResolverFromPayload(p)\n return Reflect.apply(processor, null, [resolverName, p])\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 result = processPayload(payload, getQueryFromArgs)\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 && isPlainObject(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 [TIMESTAMP_PARAM_NAME]: handleTimestamp(payload)\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 result = processPayload(payload, getMutationFromArgs)\n\n if (result !== false) {\n return result\n }\n throw new JsonqlValidationError('[getMutationArgs] Payload is malformed!', payload)\n}\n","// take out all the namespace related methods in one place for easy to find\nimport {\n JSONQL_PATH,\n PUBLIC_KEY,\n NSP_GROUP,\n PUBLIC_NAMESPACE\n} from 'jsonql-constants'\nimport { extractSocketPart } from './contract'\nconst SOCKET_NOT_FOUND_ERR = `socket not found in contract!`\nconst SIZE = 'size'\n\n/**\n * create the group using publicNamespace when there is only public\n * @param {object} socket from contract\n * @param {string} publicNamespace\n */\nfunction groupPublicNamespace(socket, publicNamespace) {\n let g = {}\n for (let resolverName in socket) {\n let params = socket[resolverName]\n g[resolverName] = params\n }\n return { size: 1, nspGroup: {[publicNamespace]: g}, publicNamespace}\n}\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 function groupByNamespace(contract) {\n let socket = extractSocketPart(contract)\n if (socket === false) {\n throw new JsonqlError('groupByNamespace', SOCKET_NOT_FOUND_ERR)\n }\n let prop = {\n [NSP_GROUP]: {},\n [PUBLIC_NAMESPACE]: null,\n [SIZE]: 0 \n }\n\n for (let resolverName in socket) {\n let params = socket[resolverName]\n let { namespace } = params\n if (namespace) {\n if (!prop[NSP_GROUP][namespace]) {\n ++prop[SIZE]\n prop[NSP_GROUP][namespace] = {}\n }\n prop[NSP_GROUP][namespace][resolverName] = params\n // get the public namespace\n if (!prop[PUBLIC_NAMESPACE] && params[PUBLIC_KEY]) {\n prop[PUBLIC_NAMESPACE] = namespace\n }\n }\n }\n \n return prop \n}\n\n/**\n * @NOTE ported from jsonql-ws-client\n * Got to make sure the connection order otherwise\n * it will hang\n * @param {object} nspGroup contract\n * @param {string} publicNamespace like the name said\n * @return {array} namespaces in order\n */\nexport function getNamespaceInOrder(nspGroup, publicNamespace) {\n let names = [] // need to make sure the order!\n for (let namespace in nspGroup) {\n if (namespace === publicNamespace) {\n names[1] = namespace\n } else {\n names[0] = namespace\n }\n }\n return names\n}\n\n/**\n * @TODO this might change, what if we want to do room with ws\n * 1. there will only be max two namespace\n * 2. when it's normal we will have the stock path as namespace\n * 3. when enableAuth then we will have two, one is jsonql/public + private\n * @param {object} config options\n * @return {array} of namespace(s)\n */\nexport function getNamespace(config) {\n const base = JSONQL_PATH\n if (config.enableAuth) {\n // the public come first @1.0.1 we use the constants instead of the user supplied value\n // @1.0.4 we use the config value again, because we could control this via the post init\n return [\n [ base , config.privateNamespace ].join('/'),\n [ base , config.publicNamespace ].join('/')\n ]\n }\n return [ base ]\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nexport function getPrivateNamespace(namespaces) {\n return namespaces.length > 1 ? namespaces[0] : false\n}\n\n/**\n * Got a problem with a contract that is public only the groupByNamespace is wrong\n * which is actually not a problem when using a fallback, but to be sure things in order\n * we could combine with the config to group it\n * @param {object} config configuration\n * @return {object} nspInfo object\n */\nexport function getNspInfoByConfig(config) {\n const { contract, enableAuth } = config\n const namespaces = getNamespace(config)\n let nspInfo = enableAuth ? groupByNamespace(contract)\n : groupPublicNamespace(contract.socket, namespaces[0])\n // add the namespaces into it as well\n return Object.assign(nspInfo, { namespaces })\n}\n\n","// There are the socket related methods ported back from \n// ws-server-core and ws-client-core \nimport {\n WS_REPLY_TYPE,\n WS_EVT_NAME,\n WS_DATA_NAME,\n TIMESTAMP_PARAM_NAME,\n ERROR_KEY,\n EMIT_REPLY_TYPE,\n EMIT_SEND_TYPE,\n ACKNOWLEDGE_REPLY_TYPE\n} from 'jsonql-constants'\nimport { JsonqlError, JsonqlValidationError } from 'jsonql-errors' \nimport isString from 'lodash-es/isString'\nimport isArray from 'lodash-es/isArray'\n\nimport { createDeliverable, formatPayload } from './params-api'\nimport { toJson, isObjectHasKey, nil } from './generic'\nimport { timestamp } from './timestamp'\n\nconst PAYLOAD_NOT_DECODED_ERR = 'payload can not decoded'\nconst WS_KEYS = [\n WS_REPLY_TYPE,\n WS_EVT_NAME,\n WS_DATA_NAME\n]\n\n/////////////////////////////////////\n// REPLY FROM SERVER //\n/////////////////////////////////////\n\n/**\n * This will be a event emit from the client using the send method \n * But we have to change the server to understand it\n * @param {string} resolverName name of resolver ot call \n * @param {array} args for the resolver\n * @param {boolean} str true then stringify it \n * @return {object} formatted payload\n */\nexport const createSendPayload = (resolverName, args, str = false) => {\n if (isString(resolverName) && isArray(args)) {\n let payload = formatPayload(args)\n // the different is we add a additonal type in the payload \n const result = createDeliverable(resolverName, payload, {type: EMIT_SEND_TYPE})\n return str ? JSON.stringify(result) : result\n }\n throw new JsonqlValidationError(`utils:socket:createSendMsg`, { \n resolverName, \n args, \n message: 'expect resolverName to be string and args to be array!'\n })\n}\n\n/**\n * We need to find the TS field and take it out from the previous payload \n * otherwise it will keep on rolling into the structure which is not what we wanted\n * @param {object} data for inspection\n * @return {object} { data: for the data to use, TS if there is any }\n */\nconst getTsFieldFromData = (data) => {\n let obj = {[TIMESTAMP_PARAM_NAME]: [], data: {}}\n if (data[TIMESTAMP_PARAM_NAME]) {\n const ts = data[TIMESTAMP_PARAM_NAME]\n obj[TIMESTAMP_PARAM_NAME] = Array.isArray(ts) ? ts : [ts]\n delete data[TIMESTAMP_PARAM_NAME]\n } \n obj.data = data\n \n return obj\n}\n\n\n/**\n * The ws doesn't have a acknowledge callback like socket.io\n * so we have to DIY one for ws and other that doesn't have it\n * @param {string} type of reply\n * @param {string} resolverName which is replying\n * @param {*} data payload\n * @param {array} [ts= []] the last received ts, if any \n * @return {string} stringify json\n */\nexport const createWsReply = (type, resolverName, data, ts = []) => {\n const obj = getTsFieldFromData(toJson(data))\n ts = ts.concat(obj[TIMESTAMP_PARAM_NAME])\n if (!ts.length) {\n ts.push(timestamp())\n }\n return JSON.stringify({\n data: {\n [WS_REPLY_TYPE]: type,\n [WS_EVT_NAME]: resolverName,\n [WS_DATA_NAME]: obj.data \n },\n [TIMESTAMP_PARAM_NAME]: ts \n })\n}\n\n// extended function \nexport const createReplyMsg = (resolverName, data, ts = []) => (\n createWsReply(EMIT_REPLY_TYPE, resolverName, data, ts)\n)\n\nexport const createAcknowledgeMsg = (resolverName, data, ts = []) => (\n createWsReply(ACKNOWLEDGE_REPLY_TYPE, resolverName, data, ts)\n)\n\n/**\n * @param {string|object} payload should be string when reply but could be transformed\n * @return {boolean} true is OK\n */\nexport const isWsReply = payload => {\n const json = isString(payload) ? toJson(payload) : payload\n const { data } = json\n if (data) {\n let result = WS_KEYS.filter(key => isObjectHasKey(data, key))\n return (result.length === WS_KEYS.length) ? data : false\n }\n return false\n}\n\n/**\n * @param {string|object} data received data\n * @param {function} [cb=nil] this is for extracting the TS field or when it's error\n * @return {object} false on failed\n */\nexport const extractWsPayload = (payload, cb = nil) => {\n try {\n const json = toJson(payload)\n // now handle the data\n let _data\n if ((_data = isWsReply(json)) !== false) {\n // note the ts property is on its own \n cb('_data', _data)\n \n return {\n data: toJson(_data[WS_DATA_NAME]),\n resolverName: _data[WS_EVT_NAME],\n type: _data[WS_REPLY_TYPE]\n }\n }\n throw new JsonqlError(PAYLOAD_NOT_DECODED_ERR, payload)\n } catch(e) {\n return cb(ERROR_KEY, e)\n }\n}\n","// this will be part of the init client sequence\n// as soon as we create a ws client\n// we listen to the on.connect event \n// then we send a init-ping event back to the server\n// and server issue a csrf token back to use \n// we use this token to create a new client and destroy the old one\nimport {\n INTERCOM_RESOLVER_NAME, \n SOCKET_PING_EVENT_NAME,\n HEADERS_KEY,\n DATA_KEY,\n CSRF_HEADER_KEY\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n extractWsPayload,\n timestamp,\n toJson \n} from 'jsonql-utils/module'\nimport {\n JsonqlError\n} from 'jsonql-errors'\nconst CSRF_HEADER_NOT_EXIST_ERR = 'CSRF header is not in the received payload'\n\n/**\n * Util method \n * @param {string} payload return from server\n * @return {object} the useful bit \n */\nfunction extractSrvPayload(payload) {\n let json = toJson(payload)\n \n if (json && typeof json === 'object') {\n // note this method expect the json.data inside\n return extractWsPayload(json)\n }\n \n throw new JsonqlError('extractSrvPayload', json)\n}\n\n/**\n * call the server to get a csrf token \n * @return {string} formatted payload to send to the server \n */\nfunction createInitPing() {\n const ts = timestamp()\n\n return createQueryStr(INTERCOM_RESOLVER_NAME, [SOCKET_PING_EVENT_NAME, ts])\n}\n\n/**\n * Take the raw on.message result back then decoded it \n * @param {*} payload the raw result from server\n * @return {object} the csrf payload\n */\nfunction extractPingResult(payload) {\n const result = extractSrvPayload(payload)\n \n if (result && result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\n }\n }\n\n throw new JsonqlError('extractPingResult', CSRF_HEADER_NOT_EXIST_ERR)\n}\n\n\n/**\n * Create a generic intercom method\n * @param {string} type the event type \n * @param {array} args if any \n * @return {string} formatted payload to send\n */\nfunction createIntercomPayload(type, ...args) {\n const ts = timestamp()\n let payload = [type].concat(args)\n payload.push(ts)\n return createQueryStr(INTERCOM_RESOLVER_NAME, payload)\n}\n\n\nexport { \n extractSrvPayload,\n createInitPing, \n extractPingResult, \n createIntercomPayload \n}","// validator numbers\n// import { NUMBER_TYPES } from './constants';\n\nimport isNaN from 'lodash-es/isNaN'\nimport isString from 'lodash-es/isString'\n/**\n * @2015-05-04 found a problem if the value is a number like string\n * it will pass, so add a chck 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 trim from 'lodash-es/trim'\nimport isString from 'lodash-es/isString'\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\n\n/**\n * @param {boolean} value expected\n * @return {boolean} true if OK\n */\nconst checkIsBoolean = function(value) {\n return value !== null && value !== undefined && typeof value === 'boolean'\n}\n\nexport default checkIsBoolean\n","// validate any thing only check if there is something\n\nimport trim from 'lodash-es/trim'\n\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 (value !== undefined && value !== '' && trim(value) !== '') {\n if (checkNull === false || (checkNull === true && value !== null)) {\n return true;\n }\n }\n return false;\n}\n\nexport default checkIsAny\n","// Good practice rule - No magic number\n\nconst 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)`\nconst PARAMS_NOT_ARRAY_ERR = `params is not an array! Did something gone wrong when you generate the contract.json?`\nconst EXCEPTION_CASE_ERR = 'Could not understand your arguments and parameter structure!'\nconst UNUSUAL_CASE_ERR = 'This is an unusual situation where the arguments are more than the params, but not mark as spread'\n\nconst RETURNS_NAME = 'returns'\n\nimport {\n \n DEFAULT_TYPE, // this is a mistake should move back to the validation\n DATA_KEY, \n ERROR_KEY,\n\n TYPE_KEY,\n OPTIONAL_KEY,\n ENUM_KEY,\n ARGS_KEY,\n CHECKER_KEY,\n ALIAS_KEY,\n\n ARRAY_TYPE_LFT,\n ARRAY_TYPE_RGT,\n \n ARRAY_TYPE,\n OBJECT_TYPE,\n STRING_TYPE,\n BOOLEAN_TYPE,\n NUMBER_TYPE,\n KEY_WORD,\n OR_SEPERATOR\n} from 'jsonql-constants'\n\n// group all export in one \nexport {\n ARGS_NOT_ARRAY_ERR,\n PARAMS_NOT_ARRAY_ERR,\n EXCEPTION_CASE_ERR,\n UNUSUAL_CASE_ERR,\n DEFAULT_TYPE,\n ARRAY_TYPE_LFT,\n ARRAY_TYPE_RGT,\n TYPE_KEY,\n OPTIONAL_KEY,\n ENUM_KEY,\n ARGS_KEY,\n CHECKER_KEY,\n ALIAS_KEY,\n ARRAY_TYPE,\n OBJECT_TYPE,\n STRING_TYPE,\n BOOLEAN_TYPE,\n NUMBER_TYPE,\n KEY_WORD,\n OR_SEPERATOR,\n\n RETURNS_NAME,\n\n DATA_KEY, \n ERROR_KEY \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\n\nimport isArray from 'lodash-es/isArray'\nimport trim from 'lodash-es/trim'\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\n\nimport isPlainObject from 'lodash-es/isPlainObject'\n// import filter from 'lodash-es/filter'\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 (_value !== undefined) {\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 Reflect.apply(checkIsObject, null, _args)\n}\n","// move the index.js code here that make more sense to find where things are\n\nimport {\n checkIsArray,\n isArrayLike,\n arrayTypeHandler,\n objectTypeHandler,\n combineFn,\n notEmpty\n} from './index'\n\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 DATA_KEY, \n ERROR_KEY \n} from './constants'\n\n\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\nimport JsonqlError from 'jsonql-errors/src/error'\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 (arg !== undefined) {\n return arg\n }\n return (param.optional === true && param.defaultvalue !== undefined ? 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 JsonqlValidationError(PARAMS_NOT_ARRAY_ERR)\n }\n if (params.length === 0) {\n return []\n }\n if (!checkIsArray(args)) {\n console.info(args)\n throw new JsonqlValidationError(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:\n let ctn = params.length;\n // this happens when we have those array. type\n let _type = [ DEFAULT_TYPE ]\n // we only looking at the first one, this might be a @BUG\n /*\n if ((tmp = isArrayLike(params[0].type[0])) !== false) {\n _type = tmp;\n } */\n // if we use the params as guide then the rest will get throw out\n // which is not what we want, instead, anything without the param\n // will get a any type and optional flag\n return args.map((arg, i) => {\n let optional = i >= ctn ? true : !!params[i].optional\n let param = params[i] || { type: _type, name: `_${i}` }\n return {\n arg: optional ? getOptionalValue(arg, param) : arg,\n index: i,\n param,\n optional\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 // v1.4.4 this fixed the problem, the root level optional is from the last fn\n if (p.optional === true || 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","/** 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 * 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 * 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","/**\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","/** 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 * 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 * @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 from 'lodash-es/isFunction'\nimport merge from 'lodash-es/merge'\nimport mapValues from 'lodash-es/mapValues'\n\nimport JsonqlEnumError from 'jsonql-errors/src/enum-error'\nimport JsonqlTypeError from 'jsonql-errors/src/type-error'\nimport JsonqlCheckerError from 'jsonql-errors/src/checker-error'\n\nimport {\n TYPE_KEY,\n OPTIONAL_KEY,\n ENUM_KEY,\n ARGS_KEY,\n CHECKER_KEY,\n KEY_WORD\n} from '../constants'\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 // log('runValidationAction', key, value)\n throw new JsonqlTypeError(key, check)\n }\n if (value[ENUM_KEY] !== false && !enumHandler(value[ARGS_KEY], value[ENUM_KEY])) {\n // log(ENUM_KEY, value[ENUM_KEY])\n throw new JsonqlEnumError(key)\n }\n if (value[CHECKER_KEY] !== false && !checkerHandler(value[ARGS_KEY], value[CHECKER_KEY])) {\n // log(CHECKER_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\n\nimport merge from 'lodash-es/merge'\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 => runValidation(args1, cb))\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\n\nimport isFunction from 'lodash-es/isFunction'\nimport isString from 'lodash-es/isString'\nimport {\n ARGS_KEY,\n TYPE_KEY,\n CHECKER_KEY,\n ENUM_KEY,\n OPTIONAL_KEY,\n ALIAS_KEY\n} from 'jsonql-constants'\n\nimport { checkIsArray } from '../array'\n// import checkIsBoolean from '../boolean'\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 constructConfig(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/**\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 * construct the actual end user method, rename with prefix get since 1.5.2\n * @param {function} validateSync validation method\n * @return {function} for performaning the actual valdiation\n */\nconst getCheckConfigAsync = function(validateSync) {\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 */\n return function(config, appProps, constantProps= {}) {\n return checkOptionsAsync(config, appProps, constantProps, validateSync)\n }\n}\n\n/**\n * copy of above but it's sync, rename with prefix get since 1.5.2\n * @param {function} validateSync validation method\n * @return {function} for performaning the actual valdiation\n */\nconst getCheckConfig = 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 getCheckConfigAsync,\n getCheckConfig,\n JSONQL_PARAMS_VALIDATOR_INFO\n}\n","// export\nimport {\n checkIsObject,\n notEmpty,\n checkIsAny,\n checkIsString,\n checkIsBoolean,\n checkIsNumber,\n checkIsArray\n} from './src'\nimport * as validator from './src/validator'\n// configuration checking\nimport * as jsonqlOptions from './src/options'\n// the two extra functions\nimport isInArray from './src/is-in-array'\nimport isObjectHasKeyFn from './src/is-key-in-object'\n\nconst isObject = checkIsObject\nconst isAny = checkIsAny\nconst isString = checkIsString\nconst isBoolean = checkIsBoolean\nconst isNumber = checkIsNumber\nconst isArray = checkIsArray\nconst isNotEmpty = notEmpty\n\nconst normalizeArgs = validator.normalizeArgs\nconst validateSync = validator.validateSync\nconst validateAsync = validator.validateAsync\n\nconst JSONQL_PARAMS_VALIDATOR_INFO = jsonqlOptions.JSONQL_PARAMS_VALIDATOR_INFO\n\nconst createConfig = jsonqlOptions.createConfig\nconst constructConfig = jsonqlOptions.constructConfigFn\n// construct the final output 1.5.2\nconst checkConfigAsync = jsonqlOptions.getCheckConfigAsync(validator.validateSync)\nconst checkConfig = jsonqlOptions.getCheckConfig(validator.validateSync)\n\nconst inArray = isInArray\nconst isObjectHasKey = isObjectHasKeyFn\n\n// check returns methods \nimport { \n checkReturns, \n checkReturnsAsync, \n checkResolverReturns, \n checkResolverReturnsAsync \n} from './src/returns'\n\n\n// group the in one \nexport {\n JSONQL_PARAMS_VALIDATOR_INFO,\n \n isObject,\n isAny,\n isString,\n isBoolean,\n isNumber,\n isArray,\n isNotEmpty,\n \n inArray,\n isObjectHasKey,\n\n normalizeArgs,\n validateSync,\n validateAsync,\n\n createConfig,\n constructConfig,\n checkConfig,\n checkConfigAsync,\n\n checkReturns, \n checkReturnsAsync, \n checkResolverReturns, \n checkResolverReturnsAsync\n}\n\n\n\n\n\n","// move the get logger stuff here\n\n// it does nothing\nconst dummyLogger = () => {}\n\n/**\n * re-use the debugOn prop to control this log method\n * @param {object} opts configuration\n * @return {function} the log function\n */\nconst getLogger = (opts) => {\n const { debugOn } = opts \n if (debugOn) {\n return (...args) => {\n Reflect.apply(console.info, console, ['[jsonql-ws-client-core]', ...args])\n }\n }\n return dummyLogger\n}\n\n/**\n * Make sure there is a log method\n * @param {object} opts configuration\n * @return {object} opts\n */\nconst getLogFn = opts => {\n const { log } = opts // 1.3.9 if we pass a log method here then we use this\n if (!log || typeof log !== 'function') {\n return getLogger(opts)\n }\n opts.log('---> getLogFn user supplied log function <---', opts)\n return log\n}\n\nexport { getLogFn }","// group all the repetitive message here\n\nexport const TAKEN_BY_OTHER_TYPE_ERR = 'You are trying to register an event already been taken by other type:'\n\n// use constants for type\nexport const ON_TYPE = 'on'\nexport const ONLY_TYPE = 'only'\nexport const ONCE_TYPE = 'once'\nexport const ONLY_ONCE_TYPE = 'onlyOnce'\nexport const MAX_CALL_TYPE = 'maxAllowCall'\nexport const NEG_RETURN = -1\n\nexport const AVAILABLE_TYPES = [\n ON_TYPE,\n ONLY_TYPE,\n ONCE_TYPE,\n ONLY_ONCE_TYPE\n]\n// the type which the callMax can execute on\nexport const ON_MAX_TYPES = [\n ON_TYPE,\n ONLY_TYPE\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 function hashCode(s) {\n\treturn s.split(\"\").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0)\n}\n\n/**\n * wrapper to make sure it string\n * @param {*} input whatever\n * @return {string} output\n */\nexport function hashCode2Str(s) {\n return hashCode(s) + ''\n}\n\n/**\n * Just check if a pattern is an RegExp object\n * @param {*} pat whatever\n * @return {boolean} false when its not\n */\nexport function isRegExp(pat) {\n return pat instanceof RegExp\n}\n\n/**\n * check if its string\n * @param {*} arg whatever\n * @return {boolean} false when it's not\n */\nexport function isString(arg) {\n return typeof arg === 'string'\n}\n\n/**\n * check if it's an integer\n * @param {*} num input number\n * @return {boolean}\n */\nexport function isInt(num) {\n if (isString(num)) {\n throw new Error(`Wrong type, we want number!`)\n }\n return !isNaN(parseInt(num))\n}\n\n/**\n * Find from the array by matching the pattern\n * @param {*} pattern a string or RegExp object\n * @return {object} regex object or false when we can not id the input\n */\nexport function getRegex(pattern) {\n switch (true) {\n case isRegExp(pattern) === true:\n return pattern\n case isString(pattern) === true:\n return new RegExp(pattern)\n default:\n return false\n }\n}\n\n\n/**\n * in array\n * @param {array} arr to search\n * @param {*} prop to search\n */\n export const inArray = (arr, prop) => !!arr.filter(v => prop === v).length\n","// Create two WeakMap store as a private keys\nexport const NB_EVENT_SERVICE_PRIVATE_STORE = new WeakMap()\nexport const NB_EVENT_SERVICE_PRIVATE_LAZY = new WeakMap()\n","// setup a base class to put all the don't know where to put methods \nimport { hashCode2Str, isString } from './utils'\nimport { AVAILABLE_TYPES } from './constants'\n\nexport default class BaseClass {\n\n constructor() {}\n\n /**\n * logger function for overwrite\n */\n logger() {}\n\n // for id if the instance is this class\n get $name() {\n return 'to1source-event'\n }\n\n // take this down in the next release\n get is() {\n return this.$name\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 (!isString(e)) {\n this.logger('(validateEvt)', e)\n\n throw new Error(`Event name must be string type! we got ${typeof e}`)\n }\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\n return true\n }\n }\n throw new Error(`callback required to be function type! we got ${typeof callback}`)\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 this.validateEvt(type)\n \n return !!AVAILABLE_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:', callback, 'payload:', payload, 'context:', ctx)\n this.$done = Reflect.apply(callback, ctx, this.toArray(payload))\n\n return this.$done // return it here first \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\n return hashCode2Str(fn.toString())\n }\n} ","// making all the functionality on it's own\n// import { WatchClass } from './watch'\n/*\nwe use a different way to do the same watch thing now\nthis.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*/\nimport { getRegex, isRegExp } from './utils'\n\nimport BaseClass from './base'\n\nexport default class SuspendClass extends BaseClass {\n\n constructor() {\n super()\n\n // suspend, release and queue\n this.__suspend_state__ = null\n // to do this proper we don't use a new prop to hold the event name pattern\n this.__pattern__ = null\n\n\n this.queueStore = new Set()\n }\n\n /**\n * start suspend\n * @return {void}\n */\n $suspend() {\n this.logger(`---> SUSPEND ALL OPS <---`)\n this.__suspend__(true)\n }\n\n /**\n * release the queue\n * @return {void}\n */\n $release() {\n this.logger(`---> RELEASE SUSPENDED QUEUE <---`)\n this.__suspend__(false)\n }\n\n /**\n * suspend event by pattern\n * @param {string} pattern the pattern search matches the event name\n * @return {void}\n */\n $suspendEvent(pattern) {\n const regex = getRegex(pattern)\n if (isRegExp(regex)) {\n this.__pattern__ = regex\n return this.$suspend()\n }\n throw new Error(`We expect a pattern variable to be string or RegExp, but we got \"${typeof regex}\" instead`)\n }\n\n /**\n * queuing call up when it's in suspend mode\n * @param {string} evt the event name\n * @param {*} args unknown number of arguments\n * @return {boolean} true when added or false when it's not\n */\n $queue(evt, ...args) {\n this.logger('($queue) get called')\n if (this.__suspend_state__ === true) {\n if (isRegExp(this.__pattern__)) { // it's better then check if its not null\n // check the pattern and decide if we want to suspend it or not\n let found = this.__pattern__.test(evt)\n if (!found) {\n return false\n }\n }\n this.logger('($queue) added to $queue', args)\n // @TODO there shouldn't be any duplicate, but how to make sure?\n this.queueStore.add([evt].concat(args))\n // return this.queueStore.size\n }\n return !!this.__suspend_state__\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 * to set the suspend and check if it's boolean value\n * @param {boolean} value to trigger\n */\n __suspend__(value) {\n if (typeof value === 'boolean') {\n const lastValue = this.__suspend_state__\n this.__suspend_state__ = value\n this.logger(`($suspend) Change from \"${lastValue}\" --> \"${value}\"`)\n if (lastValue === true && value === false) {\n this.__release__()\n }\n } else {\n throw new Error(`$suspend only accept Boolean value! we got ${typeof value}`)\n }\n }\n\n /**\n * Release the queue\n * @return {int} size if any\n */\n __release__() {\n let size = this.queueStore.size\n let pattern = this.__pattern__\n this.__pattern__ = null\n this.logger(`(release) was called with ${size}${pattern ? ' for \"' + pattern + '\"': ''} item${size > 1 ? 's' : ''}`)\n if (size > 0) {\n const queue = Array.from(this.queueStore)\n this.queueStore.clear()\n this.logger('(release 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 return size\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 {\n NEG_RETURN,\n ON_MAX_TYPES\n} from './constants'\nimport { isInt, inArray } from './utils'\n\nimport SuspendClass from './suspend'\n\nexport default class StoreService 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 // this is the new throw away map\n this.maxCountStore = new Map()\n }\n\n /**\n * We need this to pre-check the store, otherwise\n * the execution will be unable to determine the number of calls\n * @param {string} evtName event name\n * @return {number} the count of this store\n */\n getMaxStore(evtName) {\n return this.maxCountStore.get(evtName) || NEG_RETURN\n }\n\n /**\n * This is one stop shop to check and munipulate the maxStore\n * @param {*} evtName\n * @param {*} [max=null]\n * @return {number} when return -1 means removed\n */\n checkMaxStore(evtName, max = null) {\n this.logger(`===========================================`)\n this.logger('checkMaxStore start', evtName, max)\n // init the store\n if (max !== null && isInt(max)) {\n // because this is the setup phrase we just return the max value\n this.maxCountStore.set(evtName, max)\n this.logger(`Setup max store for ${evtName} with ${max}`)\n return max\n }\n if (max === null) {\n // first check if this exist in the maxStore\n let value = this.getMaxStore(evtName)\n\n this.logger('getMaxStore value', value)\n\n if (value !== NEG_RETURN) {\n if (value > 0) {\n --value\n }\n if (value > 0) {\n this.maxCountStore.set(evtName, value) // just update the value\n } else {\n this.maxCountStore.delete(evtName) // just remove it\n this.logger(`remove ${evtName} from maxStore`)\n return NEG_RETURN\n }\n }\n return value\n }\n throw new Error(`Expect max to be an integer, but we got ${typeof max} ${max}`)\n }\n\n /**\n * Wrap several get filter ops together to return the callback we are looking for\n * @param {string} evtName to search for\n * @return {array} empty array when not found\n */\n searchMapEvt(evtName) {\n const evts = this.$get(evtName, true) // return in full\n const search = evts.filter(result => {\n const [ ,,,type ] = result\n\n return inArray(ON_MAX_TYPES, type)\n })\n\n return search.length ? search : []\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\n if (store.has(evt)) {\n let content = store.get(evt)\n this.logger(`(takeFromStore) has \"${evt}\"`, content)\n store.delete(evt)\n\n return content\n }\n\n return false\n }\n throw new Error(`\"${storeName}\" is not supported!`)\n }\n\n /**\n * This was part of the $get. We take it out\n * so we could use a regex to remove more than one event\n * @param {object} store the store to return from\n * @param {string} evt event name\n * @param {boolean} full return just the callback or everything\n * @return {array|boolean} false when not found\n */\n findFromStore(evt, store, full = false) {\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 [, callback,] = l\n\n return callback\n })\n }\n return false\n }\n\n /**\n * Similar to the findFromStore, but remove\n * @param {string} evt event name\n * @param {object} store the store to remove from\n * @return {boolean} false when not found\n */\n removeFromStore(evt, store) {\n if (store.has(evt)) {\n this.logger('($off)', evt)\n\n store.delete(evt)\n\n return true\n }\n return false\n }\n\n /**\n * Take out from addToStore for reuse\n * @param {object} store the store to use\n * @param {string} evt event name\n * @return {object} the set within the store\n */\n getStoreSet(store, evt) {\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 return fnSet\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 const fnSet = this.getStoreSet(store, evt)\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\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(li => {\n let [hash,] = li\n return hash === args[0]\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\n this.logger('(checkTypeInLazyStore)', store)\n\n if (store) {\n\n return !!Array\n .from(store)\n .filter(li => {\n let [,,t] = li\n return t !== type\n }).length\n }\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) try to add \"${type}\" --> \"${evt}\" to normal store`)\n // @TODO we need to check the existing store for the type first!\n if (this.checkTypeInStore(evt, type)) {\n\n this.logger('(addToNormalStore)', `\"${type}\" --> \"${evt}\" can add to normal store`)\n\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\n return size\n }\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 this.logger(`(addToLazyStore) size: ${size}`)\n\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}\n","// The top level\nimport {\n ON_TYPE,\n ONLY_TYPE,\n ONCE_TYPE,\n ONLY_ONCE_TYPE,\n MAX_CALL_TYPE,\n ON_MAX_TYPES,\n TAKEN_BY_OTHER_TYPE_ERR,\n NEG_RETURN\n} from './constants'\nimport { isInt, inArray } from './utils'\nimport StoreService from './store-service'\n// export\nexport default class EventService extends StoreService {\n /**\n * class constructor\n */\n constructor(config = {}) {\n super(config)\n }\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}\" 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 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(`${TAKEN_BY_OTHER_TYPE_ERR} ${t}`)\n }\n this.logger(`($on)`, `call run \"${evt}\"`)\n this.run(callback, payload, context || ctx)\n size += this.addToNormalStore(evt, type, callback, context || ctx)\n })\n\n this.logger(`($on) return size ${size}`)\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\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}\" is not in the lazy store`)\n // v1.3.0 $once now allow to add multiple listeners\n return this.addToNormalStore(evt, ONCE_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 !== ONCE_TYPE) {\n throw new Error(`${TAKEN_BY_OTHER_TYPE_ERR} ${t}`)\n }\n this.logger('($once)', `call run \"${evt}\"`)\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\n let added = false\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register before call $trigger\n let nStore = this.normalStore\n\n if (!nStore.has(evt)) {\n this.logger(`($only) \"${evt}\" add to normalStore`)\n\n added = this.addToNormalStore(evt, ONLY_TYPE, callback, context)\n }\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( li => {\n const [ payload, ctx, t ] = li\n if (t && t !== ONLY_TYPE) {\n throw new Error(`${TAKEN_BY_OTHER_TYPE_ERR} ${t}`)\n }\n this.logger(`($only) call run \"${evt}\"`)\n this.run(callback, payload, context || ctx)\n })\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 added 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\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 normalStore`)\n\n added = this.addToNormalStore(evt, ONLY_ONCE_TYPE, callback, context)\n }\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 !== ONLY_ONCE_TYPE) {\n throw new Error(`${TAKEN_BY_OTHER_TYPE_ERR} ${t}`)\n }\n this.logger(`($onlyOnce) call run \"${evt}\"`)\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 * change the way how it suppose to work, instead of create another new store\n * We perform this check on the trigger end, so we set the number max\n * whenever we call the callback, we increment a value in the store\n * once it reaches that number we remove that event from the store,\n * also this will not get add to the lazy store,\n * which means the event must register before we can fire it\n * therefore we don't have to deal with the backward check\n * @param {string} evtName the event to get pre-registered\n * @param {number} max pass the max amount of callback can add to this event\n * @param {*} [ctx=null] the context the callback execute in\n * @return {function} the event handler\n */\n $max(evtName, max, ctx = null) {\n this.validateEvt(evtName)\n if (isInt(max) && max > 0) {\n // find this in the normalStore\n const fnSet = this.$get(evtName, true)\n if (fnSet !== false) {\n const evts = this.searchMapEvt(evtName)\n if (evts.length) {\n // should only have one anyway\n const [,,,type] = evts[0]\n // now init the max store\n const value = this.checkMaxStore(evtName, max)\n const _self = this\n /**\n * construct the callback\n * @param {array<*>} args\n * @return {number} \n */\n return function executeMaxCall(...args) {\n const ctn = _self.getMaxStore(evtName)\n let value = NEG_RETURN\n if (ctn > 0) {\n const fn = _self.$call(evtName, type, ctx)\n Reflect.apply(fn, _self, args)\n\n value = _self.checkMaxStore(evtName)\n if (value === NEG_RETURN) {\n _self.$off(evtName)\n return NEG_RETURN\n }\n }\n return value\n }\n }\n }\n // change in 1.1.1 because we might just call it without knowing if it's register or not\n this.logger(`The ${evtName} is not registered, can not execute non-existing event at the moment`)\n return NEG_RETURN\n }\n throw new Error(`Expect max to be an integer and greater than zero! But we got [${typeof max}]${max} instead`)\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_TYPE) {\n if (this.validateType(type)) {\n this.$off(evt)\n let method = this['$' + type]\n\n this.logger(`($replace)`, evt, callback)\n\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 this.logger(`($trigger) \"${evt}\" found`)\n // @1.8.0 to add the suspend queue\n let added = this.$queue(evt, payload, context, type)\n if (added) {\n this.logger(`($trigger) Currently suspended \"${evt}\" added to queue, nothing executed. Exit now.`)\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.logger(`($trigger) call run for ${type}:${evt}`)\n\n this.run(callback, payload, context || ctx)\n\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 aroun\n * @NOTE breaking change: v1.9.1 it return an function to accept the params as spread\n * @param {string} evt event name\n * @param {string} type of call\n * @param {object} context what context callback execute in\n * @return {*} from $trigger\n */\n $call(evt, type = false, context = null) {\n const ctx = this\n\n return function executeCall(...args) {\n let _args = [evt, args, context, type]\n\n return Reflect.apply(ctx.$trigger, ctx, _args)\n }\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 // @TODO we will allow a regex pattern to mass remove event\n this.validateEvt(evt)\n let stores = [ this.lazyStore, this.normalStore ]\n\n return !!stores\n .filter(store => store.has(evt))\n .map(store => this.removeFromStore(evt, store))\n .length\n }\n\n /**\n * return all the listener bind to that event name\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 // @TODO should we allow the same Regex to search for all?\n this.validateEvt(evt)\n let store = this.normalStore\n return this.findFromStore(evt, store, full)\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) set 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 this.logger('($done) get result:', this.result)\n if (this.keep) {\n return this.result[this.result.length - 1]\n }\n return this.result\n }\n\n /**\n * Take a look inside the stores\n * @param {number|null} idx of the store, null means all\n * @return {void}\n */\n $debug(idx = null) {\n let names = ['lazyStore', 'normalStore']\n let stores = [this.lazyStore, this.normalStore]\n if (stores[idx]) {\n this.logger(names[idx], stores[idx])\n } else {\n stores.map((store, i) => {\n this.logger(names[i], store)\n })\n }\n }\n}\n","// default\nimport To1sourceEvent from './src/event-service'\n\nexport default To1sourceEvent\n","// this will generate a event emitter and will be use everywhere\nimport EventEmitterClass from '@to1source/event'\n// create a clone version so we know which one we actually is using\nclass JsonqlWsEvt extends EventEmitterClass {\n\n constructor(logger) {\n if (typeof logger !== 'function') {\n throw new Error(`Just die here the logger is not a function!`)\n }\n logger(`---> Create a new EventEmitter <---`)\n // this ee will always come with the logger\n // because we should take the ee from the configuration\n super({ logger })\n }\n\n get name() {\n return'jsonql-ws-client-core'\n }\n}\n\n/**\n * getting the event emitter\n * @param {object} opts configuration\n * @return {object} the event emitter instance\n */\nconst getEventEmitter = opts => {\n const { log, eventEmitter } = opts\n \n if (eventEmitter) {\n log(`eventEmitter is:`, eventEmitter.name)\n return eventEmitter\n }\n \n return new JsonqlWsEvt( opts.log )\n}\n\nexport { \n getEventEmitter, \n EventEmitterClass // for other module to build from \n}\n","// group all the small functions here\nimport { EMIT_REPLY_TYPE } from 'jsonql-constants'\nimport { toArray, createEvt } from 'jsonql-utils/src/generic'\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\n\n\n/**\n * WebSocket is strict about the path, therefore we need to make sure before it goes in\n * @param {string} url input url\n * @return {string} url with correct path name\n */\nexport const fixWss = url => {\n const uri = url.toLowerCase()\n if (uri.indexOf('http') > -1) {\n if (uri.indexOf('https') > -1) {\n return uri.replace('https', 'wss')\n }\n return uri.replace('http', 'ws')\n }\n return uri\n}\n\n\n/**\n * get a stock host name from browser\n */\nexport const getHostName = () => {\n try {\n return [window.location.protocol, window.location.host].join('//')\n } catch(e) {\n throw new JsonqlValidationError(e)\n }\n}\n\n/**\n * Unbind the event\n * @param {object} ee EventEmitter\n * @param {string} namespace\n * @return {void}\n */\nexport const clearMainEmitEvt = (ee, namespace) => {\n let nsps = toArray(namespace)\n nsps.forEach(n => {\n ee.$off(createEvt(n, EMIT_REPLY_TYPE))\n })\n}\n\n\n","// constants\n\nimport {\n EMIT_REPLY_TYPE,\n JS_WS_SOCKET_IO_NAME,\n JS_WS_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_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\nconst CB_FN_NAME = 'on'\n// this is a socket only (for now) feature so we just put it here \nconst DISCONNECTED_ERROR_MSG = `You have disconnected from the socket server, please reconnect.`\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 ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n NAMESPACE_KEY,\n UNKNOWN_RESULT,\n NOT_ALLOW_OP,\n MY_NAMESPACE,\n CB_FN_NAME,\n DISCONNECTED_ERROR_MSG\n}\n","// breaking it up further to share between methods\nimport { DATA_KEY, ERROR_KEY } from 'jsonql-constants'\nimport { UNKNOWN_RESULT } from '../options/constants'\nimport { isObjectHasKey } from '../utils'\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 NOT from promise\n * @param {function} rejecter NOT from promise\n * @return {void} nothing\n */\nexport function respondHandler(data, resolver, rejecter) {\n if (isObjectHasKey(data, ERROR_KEY)) {\n // debugFn('-- rejecter called --', data[ERROR_KEY])\n rejecter(data[ERROR_KEY])\n } else if (isObjectHasKey(data, DATA_KEY)) {\n // debugFn('-- resolver called --', data[DATA_KEY])\n // @NOTE we change from calling it directly to use reflect \n // this could have another problem later when the return data is no in an array structure\n Reflect.apply(resolver, null, [...data[DATA_KEY]])\n } else {\n // debugFn('-- UNKNOWN_RESULT --', data)\n rejecter({message: UNKNOWN_RESULT, error: data})\n }\n}\n","// the actual trigger call method\nimport { ON_RESULT_FN_NAME, EMIT_REPLY_TYPE } from 'jsonql-constants'\nimport { createEvt, toArray } from '../utils'\nimport { respondHandler } from './respond-handler'\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 * @param {function} log function \n * @return {void} nothing\n */\nexport function actionCall(ee, namespace, resolverName, args = [], log) {\n // reply event \n const outEventName = createEvt(namespace, EMIT_REPLY_TYPE)\n\n log(`actionCall: ${outEventName} --> ${resolverName}`, args)\n // This is the out going call \n ee.$trigger(outEventName, [resolverName, toArray(args)])\n \n // then we need to listen to the event callback here as well\n return new Promise((resolver, rejecter) => {\n const inEventName = createEvt(namespace, resolverName, ON_RESULT_FN_NAME)\n // this cause the onResult got the result back first \n // and it should be the promise resolve first\n // @TODO we need to rewrote the respondHandler to change the problem stated above \n ee.$on(\n inEventName,\n function actionCallResultHandler(result) {\n log(`got the first result`, result)\n respondHandler(result, resolver, rejecter)\n }\n )\n })\n}\n","// setting up the send method \nimport { JsonqlValidationError } from 'jsonql-errors'\nimport {\n ON_ERROR_FN_NAME,\n SEND_MSG_FN_NAME\n} from 'jsonql-constants'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { objDefineProps, createEvt, toArray, nil } from '../utils'\nimport { actionCall } from './action-call'\n\n/** \n * pairing with the server vesrion SEND_MSG_FN_NAME\n * last of the chain so only return the resolver (fn)\n * This is now change to a getter / setter method \n * and call like this: resolver.send(...args)\n * @param {function} fn the resolver function \n * @param {object} ee event emitter instance \n * @param {string} namespace the namespace it belongs to \n * @param {string} resolverName name of the resolver \n * @param {object} params from contract \n * @param {function} log a logger function\n * @return {function} return the resolver itself \n */ \nexport const setupSendMethod = (fn, ee, namespace, resolverName, params, log) => (\n objDefineProps(\n fn, \n SEND_MSG_FN_NAME, \n nil, \n function sendHandler() {\n log(`running call getter method`)\n // let _log = (...args) => Reflect.apply(console.info, console, ['[SEND]'].concat(args))\n /** \n * This will follow the same pattern like the resolver \n * @param {array} args list of unknown argument follow the resolver \n * @return {promise} resolve the result \n */\n return function sendCallback(...args) {\n return validateAsync(args, params.params, true)\n .then(_args => {\n // @TODO check the result \n // because the validation could failed with the list of fail properties \n log('execute send', namespace, resolverName, _args)\n return actionCall(ee, namespace, resolverName, _args, log)\n })\n .catch(err => {\n // @TODO it shouldn't be just a validation error \n // it could be server return error, so we need to check \n // what error we got back here first \n log('send error', err)\n // @TODO it might not an validation error need the finalCatch here\n ee.$call(\n createEvt(namespace, resolverName, ON_ERROR_FN_NAME),\n [new JsonqlValidationError(resolverName, err)]\n )\n })\n } \n })\n)\n","// break up the original setup resolver method here\n// import { JsonqlValidationError, finalCatch } from 'jsonql-errors'\nimport {\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME\n} from 'jsonql-constants'\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { actionCall } from './action-call'\n// local\nimport { MY_NAMESPACE } from '../options/constants'\nimport { chainFns, objDefineProps, injectToFn, createEvt, isFunc } from '../utils'\nimport { respondHandler } from './respond-handler'\nimport { setupSendMethod } from './setup-send-method'\n\n\n/**\n * moved back from generator-methods \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 * @param {function} log pass the log function\n * @return {function} resolver\n */\nfunction createResolver(ee, namespace, resolverName, params, log) {\n // note we pass the new withResult=true option\n return function resolver(...args) {\n return validateAsync(args, params.params, true)\n .then(_args => actionCall(ee, namespace, resolverName, _args, log))\n .catch(finalCatch)\n }\n}\n\n/**\n * The first one in the chain, just setup a namespace prop\n * the rest are passing through\n * @param {function} fn the resolver function\n * @param {object} ee the event emitter\n * @param {string} resolverName what it said\n * @param {object} params for resolver from contract\n * @param {function} log the logger function\n * @return {array}\n */\nconst setupNamespace = (fn, ee, namespace, resolverName, params, log) => [\n injectToFn(fn, MY_NAMESPACE, namespace),\n ee,\n namespace,\n resolverName,\n params,\n log\n]\n\n/**\n * onResult handler\n */\nconst setupOnResult = (fn, ee, namespace, resolverName, params, log) => [\n objDefineProps(fn, ON_RESULT_FN_NAME, function(resultCallback) {\n if (isFunc(resultCallback)) {\n ee.$on(\n createEvt(namespace, resolverName, ON_RESULT_FN_NAME),\n function resultHandler(result) {\n respondHandler(result, resultCallback, (error) => {\n log(`Catch error: \"${resolverName}\"`, error)\n ee.$trigger(\n createEvt(namespace, resolverName, ON_ERROR_FN_NAME),\n error\n )\n })\n }\n )\n }\n }),\n ee,\n namespace,\n resolverName,\n params,\n log\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 */\nconst setupOnMessage = (fn, ee, namespace, resolverName, params, log) => [\n objDefineProps(fn, ON_MESSAGE_FN_NAME, function(messageCallback) {\n // we expect this to be a function\n if (isFunc(messageCallback)) {\n // did that add to the callback\n let onMessageCallback = (args) => {\n log(`onMessageCallback`, args)\n respondHandler(\n args, \n messageCallback, \n (error) => {\n log(`Catch error: \"${resolverName}\"`, error)\n ee.$trigger(\n createEvt(namespace, resolverName, ON_ERROR_FN_NAME),\n error\n )\n })\n }\n // register the handler for this message event\n ee.$only(\n createEvt(namespace, resolverName, ON_MESSAGE_FN_NAME),\n onMessageCallback\n )\n }\n }),\n ee,\n namespace,\n resolverName,\n params,\n log\n]\n\n/**\n * ON_ERROR_FN_NAME handler\n */\nconst setupOnError = (fn, ee, namespace, resolverName, params, log) => [\n objDefineProps(fn, ON_ERROR_FN_NAME, function(resolverErrorHandler) {\n if (isFunc(resolverErrorHandler)) {\n // please note ON_ERROR_FN_NAME can add multiple listners\n ee.$only(\n createEvt(namespace, resolverName, ON_ERROR_FN_NAME),\n resolverErrorHandler\n )\n }\n }),\n ee,\n namespace,\n resolverName,\n params,\n log\n]\n\n/**\n * Add extra property / listeners 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 * @param {function} log function\n * @return {function} resolver\n */ \nfunction setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace,\n setupOnResult,\n setupOnMessage,\n setupOnError,\n setupSendMethod\n ]\n const executor = Reflect.apply(chainFns, null, fns)\n // get the executor\n return executor(fn, ee, namespace, resolverName, params, log)\n}\n\nexport { \n createResolver, \n setupResolver \n}","// put all the resolver related methods here to make it more clear\n\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\n\nimport { \n createResolver, \n setupResolver \n} from './setup-resolver'\nimport {\n injectToFn\n} from '../utils'\n\n\n/**\n * step one get the clientmap with the namespace\n * @param {object} opts configuration\n * @param {object} ee EventEmitter\n * @param {object} nspGroup resolvers index by their namespace\n * @return {promise} resolve the clientmapped, and start the chain\n */\nexport function generateResolvers(opts, ee, nspGroup) {\n const { log } = opts\n let client= {}\n \n for (let namespace in nspGroup) {\n let list = nspGroup[namespace]\n for (let resolverName in list) {\n // resolverNames.push(resolverName)\n let params = list[resolverName]\n let fn = createResolver(ee, namespace, resolverName, params, log)\n // this should set as a getter therefore can not be overwrite by accident\n client = injectToFn(\n client,\n resolverName,\n setupResolver(namespace, resolverName, params, fn, ee, log)\n )\n }\n }\n \n // resolve the clientto start the chain\n // chain the result to allow the chain processing\n return [ client, opts, ee, nspGroup ]\n}\n\n","// move from generator-methods \n// they are global event listeners \nimport {\n createEvt,\n objDefineProps,\n isFunc\n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * This event will fire when the socket.io.on('connection') and ws.onopen\n * @param {object} client client itself\n * @param {object} opts configuration\n * @param {object} ee Event Emitter\n * @return {array} [ obj, opts, ee ]\n */\nexport function setupOnReadyListener(client, opts, ee) {\n return [\n objDefineProps(\n client,\n ON_READY_FN_NAME,\n function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n // @2020-03-19 only allow ONE onReady callback otherwise\n // it will get fire multiple times which is not what we want\n ee.$only(ON_READY_FN_NAME, onReadyCallback)\n }\n }\n ),\n opts,\n ee\n ]\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} clientthe client itself\n * @param {object} opts configuration\n * @param {object} ee Event Emitter\n * @param {object} nspGroup namespace keys\n * @return {array} [obj, opts, ee]\n */\nexport function setupNamespaceErrorListener(client, opts, ee, nspGroup) {\n return [\n objDefineProps(\n client,\n ON_ERROR_FN_NAME,\n function namespaceErrorCallbackHandler(namespaceErrorHandler) {\n if (isFunc(namespaceErrorHandler)) {\n // please note ON_ERROR_FN_NAME can add multiple listners\n for (let namespace in nspGroup) {\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, ON_ERROR_FN_NAME), namespaceErrorHandler)\n }\n }\n }\n ),\n opts,\n ee\n ]\n}\n\n","// take out from the resolver-methods\nimport {\n LOGIN_EVENT_NAME,\n LOGOUT_EVENT_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { JsonqlValidationError } from 'jsonql-errors'\nimport { injectToFn, chainFns, isString, objDefineProps, isFunc } from '../utils'\n\n\n/**\n * @UPDATE it might be better if we decoup the two http-client only emit a login event\n * Here should catch it and reload the ws client @TBC\n * break out from createAuthMethods to allow chaining call\n * @param {object} obj the main client object\n * @param {object} opts configuration\n * @param {object} ee event emitter\n * @return {array} [ obj, opts, ee ] what comes in what goes out\n */\nconst setupLoginHandler = (obj, opts, ee) => [\n injectToFn(obj, opts.loginHandlerName, function loginHandler(token) {\n if (token && isString(token)) {\n opts.log(`Received ${LOGIN_EVENT_NAME} with ${token}`)\n // @TODO add the interceptor hook\n return ee.$trigger(LOGIN_EVENT_NAME, [token])\n }\n // should trigger a global error instead @TODO\n throw new JsonqlValidationError(opts.loginHandlerName, `Unexpected token ${token}`)\n }),\n opts,\n ee\n]\n\n\n/**\n * break out from createAuthMethods to allow chaining call - final in chain\n * @param {object} obj the main client object\n * @param {object} opts configuration\n * @param {object} ee event emitter\n * @return {array} [ obj, opts, ee ] what comes in what goes out\n */\nconst setupLogoutHandler = (obj, opts, ee) => [\n injectToFn(obj, opts.logoutHandlerName, function logoutHandler(...args) {\n ee.$trigger(LOGOUT_EVENT_NAME, args)\n }),\n opts,\n ee\n]\n\n\n/**\n * This event will fire when the socket.io.on('connection') and ws.onopen\n * Plus this will check if it's the private namespace that fired the event\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @return {array} [ obj, opts, ee] what comes in what goes out\n */\nconst setupOnLoginhandler = (obj, opts, ee) => [\n objDefineProps(obj, ON_LOGIN_FN_NAME, function onLoginCallbackHandler(onLoginCallback) {\n if (isFunc(onLoginCallback)) {\n // only one callback can registered with it, TBC\n // Should this be a $onlyOnce listener after the logout \n // we add it back? \n ee.$only(ON_LOGIN_FN_NAME, onLoginCallback)\n }\n }),\n opts,\n ee\n]\n\n// @TODO future feature setup switch user\n\n\n/**\n * Create auth related methods\n * @param {object} obj the client itself\n * @param {object} opts configuration\n * @param {object} ee Event Emitter\n * @return {array} [ obj, opts, ee ] what comes in what goes out\n */\nexport function setupAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler,\n setupLogoutHandler,\n setupOnLoginhandler\n )(obj, opts, ee)\n}\n","// this is a new method that will create several\n// intercom method also reverse listen to the server\n// such as disconnect (server issue disconnect)\nimport { injectToFn, chainFns } from '../utils'\nimport { \n CONNECT_EVENT_NAME,\n CONNECTED_EVENT_NAME,\n DISCONNECT_EVENT_NAME,\n CONNECTED_PROP_KEY\n} from 'jsonql-constants'\n\n/**\n * Set up the CONNECTED_PROP_KEY to the client\n * @param {*} client \n * @param {*} opts \n * @param {*} ee \n */\nfunction setupConnectPropKey(client, opts, ee) {\n const { log } = opts \n log('[1] setupConnectPropKey')\n // we just inject a helloWorld method here\n // set up the init state of the connect\n client = injectToFn(client, CONNECTED_PROP_KEY , false, true)\n return [ client, opts, ee ]\n}\n\n\n/**\n * setup listener to the connect event \n * @param {*} client \n * @param {*} opts \n * @param {*} ee \n */\nfunction setupConnectEvtListener(client, opts, ee) {\n // @TODO do what at this point?\n const { log } = opts \n\n log(`[2] setupConnectEvtListener`)\n\n ee.$on(CONNECT_EVENT_NAME, function(...args) {\n log(`setupConnectEvtListener pass and do nothing at the moment`, args)\n })\n \n return [client, opts, ee]\n}\n\n/**\n * setup listener to the connected event \n * @param {*} client \n * @param {*} opts \n * @param {*} ee \n */\nfunction setupConnectedEvtListener(client, opts, ee) {\n const { log } = opts \n\n log(`[3] setupConnectedEvtListener`)\n\n ee.$on(CONNECTED_EVENT_NAME, function() {\n client[CONNECTED_PROP_KEY] = true\n // new action to take release the holded event queue \n const ctn = ee.$release()\n\n log(`CONNECTED_EVENT_NAME`, true, 'queue count', ctn)\n\n return {[CONNECTED_PROP_KEY]: true}\n })\n\n return [client, opts, ee]\n}\n\n/**\n * Listen to the disconnect event and set the property to the client \n * @param {*} client \n * @param {*} opts \n * @param {*} ee \n */\nfunction setupDisconnectListener(client, opts, ee) {\n const { log } = opts \n\n log(`[4] setupDisconnectListener`)\n\n ee.$on(DISCONNECT_EVENT_NAME, function() {\n client[CONNECTED_PROP_KEY] = false\n log(`CONNECTED_EVENT_NAME`, false)\n\n return {[CONNECTED_PROP_KEY]: false}\n })\n\n return [client, opts, ee]\n}\n\n/**\n * disconnect action\n * @param {*} client \n * @param {*} opts \n * @param {*} ee \n * @return {object} this is the final step to return the client\n */\nfunction setupDisconectAction(client, opts, ee) {\n const { disconnectHandlerName, log } = opts\n log(`[5] setupDisconectAction`)\n\n return injectToFn(\n client,\n disconnectHandlerName,\n function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n }\n )\n}\n\n/**\n * this is the new method that setup the intercom handler\n * also this serve as the final call in the then chain to\n * output the client\n * @param {object} client the client\n * @param {object} opts configuration\n * @param {object} ee the event emitter\n * @return {object} client\n */\nexport function setupInterCom(client, opts, ee) {\n const fns = [\n setupConnectPropKey,\n setupConnectEvtListener,\n setupConnectedEvtListener,\n setupDisconnectListener,\n setupDisconectAction\n ]\n\n const executor = Reflect.apply(chainFns, null, fns)\n return executor(client, opts, ee)\n}\n","// The final step of the setup before it returns the client\nimport { setupInterCom } from './setup-intercom'\nimport { CONNECT_EVENT_NAME, SUSPEND_EVENT_PROP_KEY } from 'jsonql-constants'\n\n/**\n * The final step to return the client\n * @param {object} obj the client\n * @param {object} opts configuration\n * @param {object} ee the event emitter\n * @return {object} client\n */\nfunction setupFinalStep(obj, opts, ee) {\n \n let client = setupInterCom(obj, opts, ee)\n // opts.log(`---> The final step to return the ws-client <---`)\n // add some debug functions\n client.verifyEventEmitter = () => ee.is\n // we add back the two things into the client\n // then when we do integration, we run it in reverse,\n // create the ws client first then the host client\n client.eventEmitter = opts.eventEmitter\n client.log = opts.log\n\n // now at this point, we are going to call the connect event\n ee.$trigger(CONNECT_EVENT_NAME, [opts, ee]) // just passing back the entire opts object\n // also we can release the queue here \n if (opts[SUSPEND_EVENT_PROP_KEY] === true) {\n opts.$releaseNamespace()\n }\n\n return client\n}\n\n\nexport { setupFinalStep }\n","// resolvers generator\n// we change the interface to return promise from v1.0.3\n// this way we make sure the obj return is correct and timely\nimport { NSP_GROUP } from 'jsonql-constants'\nimport { chainFns } from '../utils'\n\nimport { generateResolvers } from './generator-methods'\nimport {\n setupOnReadyListener,\n setupNamespaceErrorListener\n} from './global-listener'\n\nimport { setupAuthMethods } from './setup-auth-methods'\n\nimport { setupFinalStep } from './setup-final-step'\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 function callersGenerator(opts, nspMap, ee) {\n let fns = [\n generateResolvers,\n setupOnReadyListener,\n setupNamespaceErrorListener\n ]\n if (opts.enableAuth) {\n // there is a problem here, when this is a public namespace\n // it should not have a login logout event attach to it\n fns.push(setupAuthMethods)\n }\n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n // This has move outside of here, into the main method\n // the reason is we could switch around the sequence much easier\n fns.push(setupFinalStep)\n // stupid reaon!!!\n const executer = Reflect.apply(chainFns, null, fns)\n // run it\n return executer(opts, ee, nspMap[NSP_GROUP])\n}\n","// create options\nimport {\n checkConfigAsync,\n checkConfig\n} from 'jsonql-params-validator'\nimport {\n wsCoreCheckMap,\n wsCoreConstProps,\n socketCheckMap\n} from './defaults'\nimport {\n fixWss,\n getHostName,\n getEventEmitter,\n getNspInfoByConfig,\n getLogFn\n} from '../utils'\n\nimport {\n SUSPEND_EVENT_PROP_KEY\n} from 'jsonql-constants'\n\n/**\n * We need this to find the socket server type\n * @param {*} config\n * @return {string} the name of the socket server if any\n */\nfunction checkSocketClientType(config) {\n return checkConfig(config, socketCheckMap)\n}\n\n/**\n * Create a combine checkConfig for the creating the combine client\n * @param {*} configCheckMap\n * @param {*} constProps\n * @return {function} takes the user input config then resolve the configuration\n */\nfunction createCombineConfigCheck(configCheckMap, constProps) {\n const combineCheckMap = Object.assign({}, configCheckMap, wsCoreCheckMap)\n const combineConstProps = Object.assign({}, constProps, wsCoreConstProps)\n return config => checkConfigAsync(config, combineCheckMap, combineConstProps)\n}\n\n\n/**\n * wrapper method to check this already did the pre check\n * @param {object} config user supply config\n * @param {object} defaultOptions for checking\n * @param {object} constProps user supply const props\n * @return {promise} resolve to the checked opitons\n */\nfunction checkConfiguration(config, defaultOptions, constProps) {\n const defaultCheckMap= Object.assign(wsCoreCheckMap, defaultOptions)\n const wsConstProps = Object.assign(wsCoreConstProps, constProps)\n\n return checkConfigAsync(config, defaultCheckMap, wsConstProps)\n}\n\n/**\n * Taking the `then` part from the method below\n * @param {object} opts\n * @return {promise} opts all done\n */\nfunction postCheckInjectOpts(opts) {\n return Promise.resolve(opts)\n .then(opts => {\n if (!opts.hostname) {\n opts.hostname = getHostName()\n }\n // @TODO the contract now will supply the namespace information\n // and we need to use that to group the namespace call\n opts.wssPath = fixWss([opts.hostname, opts.namespace].join('/'), opts.serverType)\n // get the log function here\n opts.log = getLogFn(opts)\n\n opts.eventEmitter = getEventEmitter(opts)\n \n return opts\n })\n}\n\n/**\n * Don't want to make things confusing\n * Breaking up the opts process in one place\n * then generate the necessary parameter in another step\n * @2020-3-20 here we suspend operation by it's namespace first\n * Then in the framework part, after the connection establish we release\n * the queue\n * @param {object} opts checked --> merge --> injected\n * @return {object} {opts, nspMap, ee}\n */\nfunction createRequiredParams(opts) {\n const nspMap = getNspInfoByConfig(opts)\n const ee = opts.eventEmitter\n // @TODO here we are going to add suspend event to the namespace related methods\n const { log } = opts \n const { namespaces } = nspMap\n\n log(`namespaces`, namespaces)\n\n // next we loop the namespace and suspend all the events prefix with namespace \n if (opts[SUSPEND_EVENT_PROP_KEY] === true) {\n // we create this as a function then we can call it again \n opts.$suspendNamepsace = () => namespaces.forEach(namespace => ee.$suspendEvent(namespace))\n // then we create a new method to releas the queue \n // we prefix it with the $ to notify this is not a jsonql part methods\n opts.$releaseNamespace = () => ee.$release()\n // now run it \n opts.$suspendNamepsace()\n }\n \n return { opts, nspMap, ee }\n}\n\nexport {\n // properties\n wsCoreCheckMap,\n wsCoreConstProps,\n // functions\n checkConfiguration,\n postCheckInjectOpts,\n createRequiredParams,\n // this will just get export for integration\n checkSocketClientType,\n createCombineConfigCheck\n}\n","// the top level API\n// The goal is to create a generic method that will able to handle\n// any kind of clients\n// import { injectToFn } from 'jsonql-utils'\nimport { callersGenerator } from './callers'\nimport {\n checkConfiguration,\n postCheckInjectOpts,\n createRequiredParams\n} from './options'\n\n\n/**\n * 0.5.0 we break up the wsClientCore in two parts one without the config check\n * @param {function} setupSocketClientListener just make sure what it said it does\n * @return {function} to actually generate the client\n */\nexport function wsClientCoreAction(setupSocketClientListener) {\n /**\n * This is a breaking change, to continue the onion skin design\n * @param {object} config the already checked config\n * @return {promise} resolve the client\n */\n return function createClientAction(config = {}) {\n\n return postCheckInjectOpts(config)\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => setupSocketClientListener(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => callersGenerator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`[jsonql-ws-core-client init error]`, err)\n })\n }\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} socketClientListerner this is the one method export by various clients\n * @param {object} [configCheckMap={}] we should do all the checking in the core instead of the client\n * @param {object} [constProps={}] add this to supply the constProps from the downstream client\n * @return {function} accept a config then return the wsClient instance with all the available API\n */\nexport function wsClientCore(socketClientListener, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(\n wsClientCoreAction(socketClientListener)\n )\n}\n","// this is getting too confusing \n// therefore we move it back to the framework specific \n\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 */\nfunction createNspClient(namespace, opts) {\n const { hostname, wssPath, wsOptions, nspClient, log } = opts\n const url = namespace ? [hostname, namespace].join('/') : wssPath\n log(`createNspClient --> `, url)\n\n return 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 */\nfunction createNspAuthClient(namespace, opts) {\n const { hostname, wssPath, token, wsOptions, nspAuthClient, log } = opts\n const url = namespace ? [hostname, namespace].join('/') : wssPath\n \n log(`createNspAuthClient -->`, url)\n\n if (token && typeof token !== 'string') {\n throw new Error(`Expect token to be string, but got ${token}`)\n }\n \n return nspAuthClient(url, token, wsOptions)\n}\n\nexport {\n createNspClient,\n createNspAuthClient\n}\n","// this use by client-event-handler\nimport { ON_ERROR_FN_NAME } from 'jsonql-constants'\nimport { createEvt } from '../utils'\n\n/**\n * trigger errors on all the namespace onError handler\n * @param {object} ee Event Emitter\n * @param {array} namespaces nsps string\n * @param {string} message optional\n * @return {void}\n */\nexport function triggerNamespacesOnError(ee, namespaces, message) {\n namespaces.forEach( namespace => {\n ee.$trigger(\n createEvt(namespace, ON_ERROR_FN_NAME), \n [{ message, namespace }]\n )\n })\n}\n\n/**\n * Handle the onerror callback \n * @param {object} ee event emitter \n * @param {string} namespace which namespace has error \n * @param {*} err error object\n * @return {void} \n */\nexport const handleNamespaceOnError = (ee, namespace, err) => {\n ee.$trigger(createEvt(namespace, ON_ERROR_FN_NAME), [err])\n}","// NOT IN USE AT THE MOMENT JUST KEEP IT HERE FOR THE TIME BEING \nimport {\n LOGOUT_EVENT_NAME,\n NOT_LOGIN_ERR_MSG,\n ON_ERROR_FN_NAME,\n ON_RESULT_FN_NAME,\n DISCONNECT_EVENT_NAME,\n SUSPEND_EVENT_PROP_KEY\n} from 'jsonql-constants'\nimport { EMIT_EVT, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event Listerner placeholder when it's not connect to any nsp\n * @param {string} namespace nsp\n * @param {object} ee EventEmitter\n * @param {object} opts configuration\n * @return {void}\n */\nexport const notConnectedListener = (namespace, ee, opts) => {\n const { log } = opts \n\n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedEvtCallback(resolverName, args) {\n log(`[disconnectedListerner] hijack the ws call`, namespace, resolverName, args)\n // Now we suspend all the calls but note the existing one won't be affected \n // we need to update the methods to move everything across \n \n\n const error = {\n message: DISCONNECTED_ERROR_MSG\n }\n ee.$call(createEvt(namespace, resolverName, ON_ERROR_FN_NAME), [ error ])\n // also trigger the result Listerner, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n\n/**\n * The disconnect event Listerner, now we log the client out from everything\n * @TODO now we are another problem they disconnect, how to reconnect\n * @param {object} nsps the available nsp(s)\n * @param {array} namespaces available namespace \n * @param {object} ee eventEmitter \n * @param {object} opts configuration\n * @return {void}\n */\nexport const disconnectListener = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(\n DISCONNECT_EVENT_NAME, \n function disconnectEvtCallback() {\n triggerNamespacesOnError(ee, namespaces, DISCONNECT_EVENT_NAME)\n namespaces.forEach( namespace => { \n log(`disconnect from ${namespace}`)\n\n clearMainEmitEvt(ee, namespace)\n nsps[namespace] = null \n disconnectedListerner(namespace, ee, opts)\n })\n }\n )\n}\n\n/**\n * A Event Listerner placeholder when it's not connect to the private nsp\n * @param {string} namespace nsp\n * @param {object} ee EventEmitter\n * @param {object} opts configuration\n * @return {void}\n */\nexport const notLoginListener = (namespace, ee, opts) => {\n const { log } = opts \n\n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginListernerCallback(resolverName, args) {\n log('[notLoginListerner] hijack the ws call', namespace, resolverName, args)\n const error = { message: NOT_LOGIN_ERR_MSG }\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, ON_ERROR_FN_NAME), [ error ])\n // also trigger the result Listerner, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * Only when there is a private namespace then we bind to this event\n * @param {object} nsps the available nsp(s)\n * @param {array} namespaces available namespace \n * @param {object} ee eventEmitter \n * @param {object} opts configuration\n * @return {void}\n */\nexport const logoutEvtListener = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n // this will be available regardless enableAuth\n // because the server can log the client out\n ee.$on(\n LOGOUT_EVENT_NAME, \n function logoutEvtCallback() {\n const privateNamespace = getPrivateNamespace(namespaces)\n log(`${LOGOUT_EVENT_NAME} event triggered`)\n // disconnect(nsps, opts.serverType)\n // we need to issue error to all the namespace onError Listerner\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the Listerner to the fake one\n log(`logout from ${privateNamespace}`)\n\n clearMainEmitEvt(ee, privateNamespace)\n // we need to issue one more call to the server before we disconnect\n // now this is a catch 22, here we are not suppose to do anything platform specific\n // so that should fire before trigger this event\n // clear out the nsp\n nsps[privateNamespace] = null \n // add a NOT LOGIN error if call\n notLoginWsListerner(privateNamespace, ee, opts)\n }\n )\n}\n\n","// This is share between different clients so we export it\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\n\n/*\nInside the map call but we take it out for now and until the WebSocket version is fully working\nimport { SOCKET_IO } from '../options/constants'\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n*/\nimport { getPrivateNamespace } from 'jsonql-utils/src/namespace'\nimport { logoutEvtListener, notLoginListener } from './event-listeners'\n\n/**\n * centralize all the comm in one place\n * @param {function} bindSocketEventHandler binding the ee to ws --> this is the core bit\n * @param {object} nsps namespaced nsp\n * @return {void} nothing\n */\nexport function namespaceEventListener(bindSocketEventListener, nsps) {\n /**\n * BREAKING CHANGE instead of one flat structure\n * we return a function to accept the two\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts\n * @param {object} ee Event Emitter instance\n * @return {array} although we return something but this is the last step and nothing to do further\n */\n return (opts, nspMap, ee) => {\n // since all these params already in the opts\n const { log } = opts\n const { namespaces } = nspMap\n // @1.1.3 add isPrivate prop to id which namespace is the private nsp\n // then we can use this prop to determine if we need to fire the ON_LOGIN_PROP_NAME event\n const privateNamespace = getPrivateNamespace(namespaces)\n\n // @TODO hook up the connectedEvtHandler somewhere\n\n return namespaces.map(namespace => {\n let isPrivate = privateNamespace === namespace\n log(namespace, ` --> ${isPrivate ? 'private': 'public'} nsp --> `, nsps[namespace] !== false)\n if (nsps[namespace]) {\n log('[call bindWsHandler]', isPrivate, namespace)\n\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // Finally we binding everything together\n Reflect.apply(bindSocketEventListener, null, args)\n \n } else {\n log(`binding notLoginWsHandler to ${namespace}`)\n // a dummy placeholder\n // @TODO but it should be a not connect handler\n // when it's not login (or fail) this should be handle differently\n notLoginListener(namespace, ee, opts)\n }\n if (isPrivate) {\n log(`Has private and add logoutEvtHandler`)\n logoutEvtListener(nsps, namespaces, ee, opts)\n }\n // just return something its not going to get use anywhere\n return isPrivate\n })\n }\n}\n","// jsonql-ws-core takes over the check configuration\n// here we only have to supply the options that is unique to this client\n// create options\nimport { JS_WS_NAME } from 'jsonql-constants'\n// constant props\nconst wsClientConstProps = {\n version: '__PLACEHOLDER__', // will get replace\n serverType: JS_WS_NAME\n}\n\nexport { wsClientConstProps }\n","// pass the different type of ws to generate the client\n// this is where the framework specific code get injected\nimport { TOKEN_PARAM_NAME } from 'jsonql-constants'\nimport { fixWss } from '../modules'\nimport {\n createInitPing, \n extractPingResult\n} from '../modules'\n\n/**\n * Group the ping and get respond create new client in one\n * @param {object} ws \n * @param {object} WebSocket \n * @param {string} url\n * @param {function} resolver \n * @param {function} rejecter \n * @param {boolean} auth client or not\n * @return {promise} resolve the confirm client\n */\nfunction initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) {\n // @TODO how to we id this client can issue a CSRF\n // by origin? \n ws.onopen = function onOpenCallback() {\n ws.send(createInitPing())\n }\n\n ws.onmessage = function onMessageCallback(payload) {\n try {\n const header = extractPingResult(payload.data)\n // @NOTE the break down test in ws-client-core show no problems\n // the problem was cause by malform nspInfo that time? \n setTimeout(() => { // delay or not show no different but just on the safe side\n ws.terminate()\n }, 50)\n const newWs = new WebSocket(url, Object.assign(wsOptions, header)) \n resolver(newWs) \n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\n }\n\n return ws // just return it\n}\n\n/**\n * less duplicated code the better \n * @param {object} WebSocket \n * @param {string} url formatted url\n * @param {object} options or not\n * @return {promise} resolve the actual verified client\n */\nfunction asyncConnect(WebSocket, url, options) {\n \n return new Promise((resolver, rejecter) => { \n const unconfirmClient = new WebSocket(url, options)\n \n return initPingAction(unconfirmClient, WebSocket, url, resolver, rejecter, options)\n })\n}\n\n\n/**\n * The bug was in the wsOptions where ws don't need it but socket.io do\n * therefore the object was pass as second parameter!\n * @NOTE here we only return a method to create the client, it might not get call \n * @param {object} WebSocket the client or node version of ws\n * @param {object} opts this is a breaking change we will init the client twice\n * @param {boolean} [auth = false] if it's auth then 3 param or just one\n * @return {function} the client method to connect to the ws socket server\n */\nfunction initWebSocketClient(WebSocket, opts, auth = false) {\n const { log } = opts\n if (auth === false) {\n /**\n * Create a non-protected client\n * @param {string} url \n * @param {object} [wsOptions={}]\n * @return {promise} resolve to the confirmed client\n */\n return function createWsClient(url, wsOptions = {}) {\n const _url = fixWss(url)\n log(`nspClient: \\n${_url}\\n`, wsOptions)\n\n return asyncConnect(WebSocket, _url, wsOptions)\n }\n }\n\n /**\n * Create a client with auth token\n * @param {string} url start with ws:// @TODO check this?\n * @param {string} token the jwt token\n * @param {object} [wsOptions={}] extra options pass to the WebSocket object\n * @return {object} ws instance\n */\n return function createWsAuthClient(url, token, wsOptions = {}) {\n const ws_url = fixWss(url)\n // console.log('what happen here?', url, ws_url, token)\n const _url = token && typeof token === 'string' ? `${ws_url}?${TOKEN_PARAM_NAME}=${token}` : ws_url\n log(`nspAuthClient: \\n${_url}\\n`, wsOptions)\n\n return asyncConnect(WebSocket, _url, wsOptions)\n }\n}\n\nexport { initWebSocketClient }","// @BUG when call disconnected\n// this keep causing an \"Disconnect call failed TypeError: Cannot read property 'readyState' of null\"\n// I think that is because it's not login then it can not be disconnect\n// how do we track this state globally\nimport { \n LOGIN_EVENT_NAME, \n CONNECT_EVENT_NAME \n} from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * when we received a login event \n * from the http-client or the standalone login call \n * we received a token here --> update the opts then trigger \n * the CONNECT_EVENT_NAME again\n * @param {object} opts configurations\n * @param {object} nspMap contain all the required info\n * @param {object} ee event emitter\n * @return {void}\n */\nexport function loginEventListener(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n log(`[4] loginEventHandler`)\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n\n log('createClient LOGIN_EVENT_NAME $only handler')\n // clear out all the event binding\n clearMainEmitEvt(ee, namespaces)\n // reload the nsp and rebind all the events\n opts.token = tokenFromLoginAction \n ee.$trigger(CONNECT_EVENT_NAME, [opts, ee]) // don't need to pass the nspMap \n })\n}\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 * 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 * 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 * 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 * 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","/**\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 * 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","/** 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 * 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 * 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 * 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 * 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 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 * 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","/** 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","/**\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 * 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 `_.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","/** 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 * 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 * 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","/**\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 * 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","/** 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","// break it out on its own because\n// it's building from the lodash-es from scratch\n// according to this discussion https://github.com/lodash/lodash/issues/3298\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport merge from 'lodash-es/merge'\n\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 * @param {boolean} asObject if true then merge the result object\n * @return {object} promise resolved with the array of promises resolved results\n */\nexport function chainPromises(promises, asObject = false) {\n return promises.reduce((promiseChain, currentTask) => (\n promiseChain.then(chainResults => (\n currentTask.then(currentResult => (\n asObject === false ? [...chainResults, currentResult] : merge(chainResults, currentResult)\n ))\n ))\n ), Promise.resolve(\n asObject === false ? [] : (isPlainObject(asObject) ? asObject : {})\n ))\n}\n\n\n/**\n * This one return a different result from the chainPromises\n * it will be the same like chainFns that take one promise resolve as the next fn parameter\n * @param {function} initPromise a function that accept param and resolve result\n * @param {array} promises array of function pass that resolve promises\n * @return {promise} resolve the processed result\n */\nexport function chainProcessPromises(initPromise, ...promises) {\n return (...args) => (\n promises.reduce((promiseChain, currentTask) => (\n promiseChain.then(chainResult => (\n currentTask(chainResult)\n )\n )\n ), Reflect.apply(initPromise, null, args))\n )\n}\n","// actually binding the event client to the socket client\nimport {\n createNspClient,\n createNspAuthClient\n} from './modules'\nimport {\n chainPromises \n} from 'jsonql-utils/src/chain-promises'\n\n/**\n * Because the nsps can be throw away so it doesn't matter the scope\n * this will get reuse again\n * @NOTE when we enable the standalone method this sequence will not change \n * only call and reload\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 {promise} resolve the nsps namespace with namespace as key\n */\nconst createNsp = function(opts, nspMap, token = null) {\n // we leave the token param out because it could get call by another method\n token = token || opts.token \n let { publicNamespace, namespaces } = nspMap\n const { log } = opts \n log(`createNspAction`, 'publicNamespace', publicNamespace, 'namespaces', namespaces)\n \n // reverse the namespaces because it got stuck for some reason\n // const reverseNamespaces = namespaces.reverse()\n if (opts.enableAuth) {\n return chainPromises(\n namespaces.map((namespace, i) => {\n if (i === 0) {\n if (token) {\n opts.token = token\n log('create createNspAuthClient at run time')\n return createNspAuthClient(namespace, opts)\n }\n return Promise.resolve(false)\n }\n return createNspClient(namespace, opts)\n })\n )\n .then(results => \n results.map((result, i) => \n ({ [namespaces[i]]: result }))\n .reduce((a, b) => Object.assign(a, b), {})\n )\n }\n\n return createNspClient(false, opts)\n .then(nsp => ({[publicNamespace]: nsp}))\n}\n\nexport { createNsp }\n","// bunch of generic helpers\n\nimport isArray from 'lodash-es/isArray'\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport trim from 'lodash-es/trim'\n\n/**\n * DIY in Array\n * @param {array} arr to check from\n * @param {*} value to check against\n * @return {boolean} true on found\n */\nexport const inArray = (arr, value) => !!arr.filter(a => a === value).length\n\n// quick and dirty to turn non array to array\nexport const toArray = (arg) => isArray(arg) ? arg : [arg]\n\n/**\n * parse string to json or just return the original value if error happened\n * @param {*} n input\n * @param {boolean} [t=true] or throw\n * @return {*} json object on success\n */\nexport const parseJson = function(n, t=true) {\n try {\n return JSON.parse(n)\n } catch(e) {\n if (t) {\n return n\n }\n throw new Error(e)\n }\n}\n\n/**\n * @param {object} obj for search\n * @param {string} key target\n * @return {boolean} true on success\n */\nexport const isObjectHasKey = function(obj, key) {\n try {\n const keys = Object.keys(obj)\n return inArray(keys, key)\n } catch(e) {\n // @BUG when the obj is not an OBJECT we got some weird output\n return false\n }\n}\n\n/**\n * create a event name\n * @param {string[]} args\n * @return {string} event name for use\n */\nexport const createEvt = (...args) => args.join('_')\n\n/**\n * simple util method to get the value\n * @param {string} name of the key\n * @param {object} obj to take value from\n * @return {*} the object value id by name or undefined\n */\nexport const getConfigValue = (name, obj) => (\n obj && isPlainObject(obj) ? ( (name in obj) ? obj[name] : undefined ) : undefined\n)\n\n/**\n * small util to make sure the return value is valid JSON object\n * @param {*} n input\n * @return {object} correct JSON object\n */\nexport const toJson = n => {\n if (typeof n === 'string') {\n return parseJson(n)\n }\n return parseJson(JSON.stringify(n))\n}\n\n/**\n * Check several parameter that there is something in the param\n * @param {*} param input\n * @return {boolean}\n */\nexport const isNotEmpty = function(param) {\n return param !== undefined && param !== false && param !== null && trim(param) !== ''\n}\n\n/**\n * Simple check if the prop is function\n * @param {*} prop input\n * @return {boolean} true on success\n */\nexport const isFunc = prop => {\n if (typeof prop === 'function') {\n return true;\n }\n console.error(`Expect to be Function type! Got ${typeof prop}`)\n}\n\n/**\n * Shorthand method for Object.assign \n * @param {array} args \n * @return {object} merge together object by key \n */\nexport const assign = (...args) => Reflect.apply(Object.assign, Object, args)\n \n/** \n * generic placeholder function\n * @return {boolean} false \n */\nexport const nil = () => false\n\n/**\n * generic turn config into immutatble \n */\nexport const freeze = config => Object.freeze(config)","// 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","/**\n * @param {boolean} sec return in second or not\n * @return {number} timestamp\n */\nexport const timestamp = (sec = false) => {\n let time = Date.now()\n return sec ? Math.floor( time / 1000 ) : time\n}\n","// ported from jsonql-params-validator\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 TIMESTAMP_PARAM_NAME\n} from 'jsonql-constants'\n\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\n\nimport isArray from 'lodash-es/isArray'\nimport isString from 'lodash-es/isString'\nimport isPlainObject from 'lodash-es/isPlainObject'\n\nimport { timestamp } from './timestamp'\nimport { parseJson } from './generic'\n\n/**\n * check if the payload has a timestamp field, then append a new timestamp to it\n * @param {object} payload from the com\n * @return {array} timestamp field with an array value\n */\nexport const handleTimestamp = payload => {\n let ts = payload[TIMESTAMP_PARAM_NAME]\n if (!isArray(ts)) {\n ts = [ts]\n }\n ts.push( timestamp() )\n\n return ts\n}\n\n/**\n * make sure it's an object (it was call formatPayload but it doesn't make sense)\n * @param {*} payload the object comes in could be string based\n * @return {object} the transformed payload\n */\nexport const toPayload = payload => isString(payload) ? parseJson(payload) : payload\n\n/**\n * @param {*} args arguments to send\n *@return {object} formatted payload\n */\nexport const formatPayload = (args) => (\n { [QUERY_ARG_NAME]: args }\n)\n\n/**\n * extract the resolver name from the payload \n * @param {object} payload\n * @return {string} resolver name \n */\nexport function getResolverFromPayload(payload) {\n const keys = Object.keys(payload)\n return keys.filter(key => key !== TIMESTAMP_PARAM_NAME)[0]\n}\n\n/**\n * wrapper method to add the timestamp as well\n * @param {string} resolverName name of the resolver\n * @param {*} payload what is sending \n * @param {object} extra additonal property we want to merge into the deliverable\n * @return {object} delierable\n */\nexport function createDeliverable(resolverName, payload, extra = {}) {\n return Object.assign({\n [resolverName]: payload,\n [TIMESTAMP_PARAM_NAME]: [ timestamp() ]\n }, extra)\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) && isArray(args)) {\n let payload = formatPayload(args)\n if (jsonp === true) {\n return payload\n }\n return createDeliverable(resolverName, payload)\n }\n throw new JsonqlValidationError('utils:params-api:createQuery', { \n message: `expect resolverName to be string and args to be array!`,\n resolverName, \n args \n })\n}\n\n/**\n * string version of the createQuery\n * @return {string}\n */\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 createDeliverable(resolverName, _payload)\n }\n throw new JsonqlValidationError(`[createMutation] expect resolverName to be string!`, { resolverName, payload, condition })\n}\n\n/**\n * string version of createMutation\n * @return {string}\n */\nexport function createMutationStr(resolverName, payload, condition = {}, jsonp = false) {\n return JSON.stringify(createMutation(resolverName, payload, condition, jsonp))\n}\n\n/**\n * Extract the parts from payload and format for use\n * @param {string} resolverName name of fn\n * @param {object} payload the incoming json\n * @return {object|boolean} false on failed\n */\nexport function getQueryFromArgs(resolverName, payload) {\n if (resolverName && isPlainObject(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 [TIMESTAMP_PARAM_NAME]: handleTimestamp(payload)\n }\n }\n }\n return false\n}\n\n/**\n * Share function so no repeat\n * @param {object} payload the payload from client\n * @param {function} processor the last get result method\n * @return {*} result processed result\n */\nfunction processPayload(payload, processor) {\n const p = toPayload(payload)\n const resolverName = getResolverFromPayload(p)\n return Reflect.apply(processor, null, [resolverName, p])\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 result = processPayload(payload, getQueryFromArgs)\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 && isPlainObject(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 [TIMESTAMP_PARAM_NAME]: handleTimestamp(payload)\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 result = processPayload(payload, getMutationFromArgs)\n\n if (result !== false) {\n return result\n }\n throw new JsonqlValidationError('[getMutationArgs] Payload is malformed!', payload)\n}\n","// There are the socket related methods ported back from \n// ws-server-core and ws-client-core \nimport {\n WS_REPLY_TYPE,\n WS_EVT_NAME,\n WS_DATA_NAME,\n TIMESTAMP_PARAM_NAME,\n ERROR_KEY,\n EMIT_REPLY_TYPE,\n EMIT_SEND_TYPE,\n ACKNOWLEDGE_REPLY_TYPE\n} from 'jsonql-constants'\nimport { JsonqlError, JsonqlValidationError } from 'jsonql-errors' \nimport isString from 'lodash-es/isString'\nimport isArray from 'lodash-es/isArray'\n\nimport { createDeliverable, formatPayload } from './params-api'\nimport { toJson, isObjectHasKey, nil } from './generic'\nimport { timestamp } from './timestamp'\n\nconst PAYLOAD_NOT_DECODED_ERR = 'payload can not decoded'\nconst WS_KEYS = [\n WS_REPLY_TYPE,\n WS_EVT_NAME,\n WS_DATA_NAME\n]\n\n/////////////////////////////////////\n// REPLY FROM SERVER //\n/////////////////////////////////////\n\n/**\n * This will be a event emit from the client using the send method \n * But we have to change the server to understand it\n * @param {string} resolverName name of resolver ot call \n * @param {array} args for the resolver\n * @param {boolean} str true then stringify it \n * @return {object} formatted payload\n */\nexport const createSendPayload = (resolverName, args, str = false) => {\n if (isString(resolverName) && isArray(args)) {\n let payload = formatPayload(args)\n // the different is we add a additonal type in the payload \n const result = createDeliverable(resolverName, payload, {type: EMIT_SEND_TYPE})\n return str ? JSON.stringify(result) : result\n }\n throw new JsonqlValidationError(`utils:socket:createSendMsg`, { \n resolverName, \n args, \n message: 'expect resolverName to be string and args to be array!'\n })\n}\n\n/**\n * We need to find the TS field and take it out from the previous payload \n * otherwise it will keep on rolling into the structure which is not what we wanted\n * @param {object} data for inspection\n * @return {object} { data: for the data to use, TS if there is any }\n */\nconst getTsFieldFromData = (data) => {\n let obj = {[TIMESTAMP_PARAM_NAME]: [], data: {}}\n if (data[TIMESTAMP_PARAM_NAME]) {\n const ts = data[TIMESTAMP_PARAM_NAME]\n obj[TIMESTAMP_PARAM_NAME] = Array.isArray(ts) ? ts : [ts]\n delete data[TIMESTAMP_PARAM_NAME]\n } \n obj.data = data\n \n return obj\n}\n\n\n/**\n * The ws doesn't have a acknowledge callback like socket.io\n * so we have to DIY one for ws and other that doesn't have it\n * @param {string} type of reply\n * @param {string} resolverName which is replying\n * @param {*} data payload\n * @param {array} [ts= []] the last received ts, if any \n * @return {string} stringify json\n */\nexport const createWsReply = (type, resolverName, data, ts = []) => {\n const obj = getTsFieldFromData(toJson(data))\n ts = ts.concat(obj[TIMESTAMP_PARAM_NAME])\n if (!ts.length) {\n ts.push(timestamp())\n }\n return JSON.stringify({\n data: {\n [WS_REPLY_TYPE]: type,\n [WS_EVT_NAME]: resolverName,\n [WS_DATA_NAME]: obj.data \n },\n [TIMESTAMP_PARAM_NAME]: ts \n })\n}\n\n// extended function \nexport const createReplyMsg = (resolverName, data, ts = []) => (\n createWsReply(EMIT_REPLY_TYPE, resolverName, data, ts)\n)\n\nexport const createAcknowledgeMsg = (resolverName, data, ts = []) => (\n createWsReply(ACKNOWLEDGE_REPLY_TYPE, resolverName, data, ts)\n)\n\n/**\n * @param {string|object} payload should be string when reply but could be transformed\n * @return {boolean} true is OK\n */\nexport const isWsReply = payload => {\n const json = isString(payload) ? toJson(payload) : payload\n const { data } = json\n if (data) {\n let result = WS_KEYS.filter(key => isObjectHasKey(data, key))\n return (result.length === WS_KEYS.length) ? data : false\n }\n return false\n}\n\n/**\n * @param {string|object} data received data\n * @param {function} [cb=nil] this is for extracting the TS field or when it's error\n * @return {object} false on failed\n */\nexport const extractWsPayload = (payload, cb = nil) => {\n try {\n const json = toJson(payload)\n // now handle the data\n let _data\n if ((_data = isWsReply(json)) !== false) {\n // note the ts property is on its own \n cb('_data', _data)\n \n return {\n data: toJson(_data[WS_DATA_NAME]),\n resolverName: _data[WS_EVT_NAME],\n type: _data[WS_REPLY_TYPE]\n }\n }\n throw new JsonqlError(PAYLOAD_NOT_DECODED_ERR, payload)\n } catch(e) {\n return cb(ERROR_KEY, e)\n }\n}\n","// taken out from the bind-socket-event-handler \nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\nimport { createIntercomPayload } from '../modules'\n\n/**\n * This is the actual logout (terminate socket connection) handler \n * There is another one that is handle what should do when this happen \n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nexport function disconnectEventListener(ee, ws) {\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(DISCONNECT_EVENT_NAME, function closeEvtHandler() {\n try {\n // @TODO we need find a way to get the userdata\n ws.send(createIntercomPayload(LOGOUT_EVENT_NAME))\n log('terminate ws connection')\n ws.terminate()\n } catch(e) {\n console.error('ws.terminate error', e)\n }\n })\n}","// the WebSocket main handler\nimport {\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME,\n ON_ERROR_FN_NAME\n} from 'jsonql-constants'\nimport {\n createQueryStr,\n createEvt,\n extractWsPayload\n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError\n} from '../modules'\nimport { \n disconnectEventListener\n} from './disconnect-event-listener'\n\n/**\n * in some edge case 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 * @return {undefined} nothing return\n */\nexport const errorTypeHandler = (ee, namespace, resolverName, json) => {\n let evt = [namespace]\n if (resolverName) {\n evt.push(resolverName)\n }\n evt.push(ON_ERROR_FN_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 event to socket normally\n * @param {string} namespace\n * @param {object} ws the nsp\n * @param {object} ee EventEmitter\n * @param {boolean} isPrivate to id if this namespace is private or not\n * @param {object} opts configuration\n * @return {object} promise resolve after the onopen event\n */\nexport function bindSocketEventHandler(namespace, ws, ee, isPrivate, opts) {\n const { log } = opts\n let onReadCalls = 2\n // setup the logut event listener \n // this will hear the event and actually call the ws.terminate\n if (isPrivate) {\n log('Private namespace', namespace, ' binding to the DISCONNECT ws.terminate')\n disconnectEventListener(ee, ws)\n }\n // log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n\n log('=== ws.onopen listened -->', namespace)\n // we just call the onReady\n ee.$trigger(ON_READY_FN_NAME, [namespace])\n // we only want to allow it get call twice (number of namespaces)\n --onReadCalls\n if (onReadCalls === 0) {\n ee.$off(ON_READY_FN_NAME)\n }\n\n // need an extra parameter here to id the private nsp\n if (isPrivate) {\n log(`isPrivate and fire the ${ON_LOGIN_FN_NAME}`)\n ee.$call(ON_LOGIN_FN_NAME)(namespace)\n }\n // add listener only after the open is called\n ee.$only(\n createEvt(namespace, EMIT_REPLY_TYPE),\n /**\n * actually send the payload to server\n * @param {string} resolverName\n * @param {array} args NEED TO CHECK HOW WE PASS THIS!\n */\n function wsMainOnEvtHandler(resolverName, args) {\n const payload = createQueryStr(resolverName, args)\n log('ws.onopen.send', resolverName, args, payload)\n\n ws.send(payload)\n }\n )\n }\n\n // reply\n // If we change it to the event callback style\n // then the payload will just be the payload and fucks up the extractWsPayload call @TODO\n ws.onmessage = function onMessageCallback(payload) {\n log(`ws.onmessage raw payload`, payload.data)\n \n // console.log(`on.message`, typeof payload, payload)\n try {\n // log(`ws.onmessage raw payload`, payload)\n // @TODO the payload actually contain quite a few things - is that changed?\n // type: message, data: data_send_from_server\n const json = extractWsPayload(payload.data)\n const { resolverName, type } = json\n\n log('Respond from server', type, json)\n\n switch (type) {\n case EMIT_REPLY_TYPE:\n let e1 = createEvt(namespace, resolverName, ON_MESSAGE_FN_NAME)\n let r = ee.$call(e1)(json)\n \n log(`EMIT_REPLY_TYPE`, e1, r)\n break\n case ACKNOWLEDGE_REPLY_TYPE:\n let e2 = createEvt(namespace, resolverName, ON_RESULT_FN_NAME)\n let x2 = ee.$call(e2)(json)\n\n log(`ACKNOWLEDGE_REPLY_TYPE`, e2, x2)\n break\n case ERROR_KEY:\n // this is handled error and we won't throw it\n // we need to extract the error from json\n log(`ERROR_KEY`)\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 log('Unhandled event!', json)\n errorTypeHandler(ee, namespace, resolverName, json)\n // let error = {error: {'message': 'Unhandled event!', type}};\n // ee.$trigger(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [error])\n }\n } catch(e) {\n log(`ws.onmessage error`, e)\n errorTypeHandler(ee, namespace, false, e)\n }\n }\n // when the server close the connection\n ws.onclose = function onCloseCallback() {\n log('ws.onclose callback')\n // @TODO what to do with this\n // ee.$trigger(LOGOUT_EVENT_NAME, [namespace])\n }\n // add a onerror event handler here\n ws.onerror = function onErrorCallback(err) {\n // trigger a global error event\n log(`ws.onerror`, err)\n handleNamespaceOnError(ee, namespace, err)\n }\n \n // we don't bind the logut here and just return the ws \n return ws \n}\n","// take out from the bind-framework-to-jsonql \nimport { CONNECT_EVENT_NAME } from 'jsonql-constants'\nimport { namespaceEventListener } from '../modules'\nimport { createNsp } from '../create-nsp'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * This is the hard of establishing the connection and binding to the jsonql events \n * @param {*} nspMap \n * @param {*} ee event emitter\n * @param {function} log function to show internal \n * @return {void}\n */\nexport function connectEventListener(nspMap, ee, log) {\n log(`[2] setup the CONNECT_EVENT_NAME`)\n // this is a automatic trigger from within the framework\n ee.$only(CONNECT_EVENT_NAME, function connectEventNameHandler($config, $ee) {\n log(`[3] CONNECT_EVENT_NAME`, $ee)\n\n return createNsp($config, nspMap)\n .then(nsps => namespaceEventListener(bindSocketEventHandler, nsps))\n .then(listenerFn => listenerFn($config, nspMap, $ee))\n })\n\n // log(`[3] after setup the CONNECT_EVENT_NAME`)\n}","// share method to create the wsClientResolver\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\nimport { initWebSocketClient } from './init-websocket-client'\nimport { \n loginEventListener, \n connectEventListener \n} from '../listeners'\n\n/**\n * Create the framework <---> jsonql client binding\n * @param {object} frameworkModule the different WebSocket module\n * @return {function} the wsClientResolver\n */\nfunction bindWebsocketToJsonql(frameworkModule) {\n /**\n * wsClientResolver\n * @param {object} opts configuration\n * @param {object} nspMap from the contract\n * @param {object} ee instance of the eventEmitter\n * @return {object} passing the same 3 input out with additional in the opts\n */\n return function createClientBindingAction(opts, nspMap, ee) {\n const { log } = opts\n\n log(`There is problem here with passing the opts`, opts)\n\n opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, opts)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, opts, true) \n // debug \n log(`[1] bindWebsocketToJsonql`, ee.$name, nspMap)\n // @2020-03-20 @NOTE \n \n connectEventListener(nspMap, ee, log)\n \n // next we need to setup the login event handler\n // But the same design (see above) when we received a login event \n // from the http-client or the standalone login call \n // we received a token here --> update the opts then trigger \n // the CONNECT_EVENT_NAME again\n loginEventListener(opts, nspMap, ee)\n\n log(`just before returing the values for the next operation from createClientBindingAction`)\n\n // we just return what comes in\n return { opts, nspMap, ee }\n }\n}\n\nexport { bindWebsocketToJsonql }","// this will be the news style interface that will pass to the jsonql-ws-client\n// then return a function for accepting an opts to generate the final\n// client api\nimport WebSocket from 'ws'\nimport createWebSocketBinding from '../core/create-websocket-binding'\n\n/**\n * @param {object} opts configuration\n * @param {object} nspMap from the contract\n * @param {object} ee instance of the eventEmitter\n * @return {object} passing the same 3 input out with additional in the opts\n */\nexport default createWebSocketBinding(WebSocket)\n","// this is the module entry point for node client\nimport {\n wsClientCore\n} from './core/modules'\nimport { wsClientConstProps } from './options'\n\nimport setupSocketClientListener from './node/setup-socket-client-listener'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n \n return wsClientCore(\n setupSocketClientListener, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )(config)\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;ACAA;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;ACAA;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;;;;;;;;"}
\ No newline at end of file
diff --git a/packages/@jsonql/ws/module.js b/packages/@jsonql/ws/module.js
index be621141565a0fcda866cfd09109379147a970ec..6db4d66709bef4ae5fd75c18926b0bff0a2a2cb4 100644
--- a/packages/@jsonql/ws/module.js
+++ b/packages/@jsonql/ws/module.js
@@ -8,9 +8,9 @@ import {
getEventEmitter,
EventEmitterClass
} from './src/create-combine-client'
-import frameworkSocketEngine from './src/core/framework-socket-engine'
+import setupSocketClientListener from './src/core/setup-socket-client-listener'
-const createCombineWsClient = createCombineWsClientConstructor(frameworkSocketEngine)
+const createCombineWsClient = createCombineWsClientConstructor(setupSocketClientListener)
export {
createCombineWsClient,
diff --git a/packages/@jsonql/ws/node.js b/packages/@jsonql/ws/node.js
index 81955d3853fbe5d479f44efd4b5f70fd49fc1f15..6e140d84a9a963237f733f1638b0f1ca6eea0f05 100644
--- a/packages/@jsonql/ws/node.js
+++ b/packages/@jsonql/ws/node.js
@@ -1,2 +1,2 @@
-"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t,e=(t=require("ws"))&&"object"==typeof t&&"default"in t?t.default:t,r={version:"version: 1.2.0 module: cjs-module",serverType:"ws"},n=Array.isArray,o="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},i="object"==typeof o&&o&&o.Object===Object&&o,a="object"==typeof self&&self&&self.Object===Object&&self,u=i||a||Function("return this")(),c=u.Symbol,s=Object.prototype,f=s.hasOwnProperty,l=s.toString,p=c?c.toStringTag:void 0;var h=Object.prototype.toString;var v=c?c.toStringTag:void 0;function g(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":v&&v in Object(t)?function(t){var e=f.call(t,p),r=t[p];try{t[p]=void 0;var n=!0}catch(t){}var o=l.call(t);return n&&(e?t[p]=r:delete t[p]),o}(t):function(t){return h.call(t)}(t)}function d(t,e){return function(r){return t(e(r))}}var y=d(Object.getPrototypeOf,Object);function _(t){return null!=t&&"object"==typeof t}var b=Function.prototype,m=Object.prototype,j=b.toString,w=m.hasOwnProperty,O=j.call(Object);function S(t){if(!_(t)||"[object Object]"!=g(t))return!1;var e=y(t);if(null===e)return!0;var r=w.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&j.call(r)==O}function E(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var i=Array(o);++n-1;);return r}(n,o),function(t,e){for(var r=t.length;r--&&z(e,t[r],0)>-1;);return r}(n,o)+1).join("")}var V=function(t){return n(t)?t:[t]},Y=function(t,e){void 0===e&&(e=!0);try{return JSON.parse(t)}catch(r){if(e)return t;throw new Error(r)}},K=function(t,e){try{var r=Object.keys(t);return n=e,!!r.filter((function(t){return t===n})).length}catch(t){return!1}var n},Q=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return t.join("_")},X=function(t){return Y("string"==typeof t?t:JSON.stringify(t))},Z=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},tt=function(){return!1},et=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return Reflect.apply(e,null,V(t))}),Reflect.apply(t,null,r))}};function rt(t,e){return t===e||t!=t&&e!=e}function nt(t,e){for(var r=t.length;r--;)if(rt(t[r][0],e))return r;return-1}var ot=Array.prototype.splice;function it(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1},it.prototype.set=function(t,e){var r=this.__data__,n=nt(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};function ut(t){if(!at(t))return!1;var e=g(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}var ct,st=u["__core-js_shared__"],ft=(ct=/[^.]+$/.exec(st&&st.keys&&st.keys.IE_PROTO||""))?"Symbol(src)_1."+ct:"";var lt=Function.prototype.toString;function pt(t){if(null!=t){try{return lt.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var ht=/^\[object .+?Constructor\]$/,vt=Function.prototype,gt=Object.prototype,dt=vt.toString,yt=gt.hasOwnProperty,_t=RegExp("^"+dt.call(yt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function bt(t){return!(!at(t)||(e=t,ft&&ft in e))&&(ut(t)?_t:ht).test(pt(t));var e}function mt(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return bt(r)?r:void 0}var jt=mt(u,"Map"),wt=mt(Object,"create");var Ot=Object.prototype.hasOwnProperty;var St=Object.prototype.hasOwnProperty;function Et(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&t<=9007199254740991}function Kt(t){return null!=t&&Yt(t.length)&&!ut(t)}var Qt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Xt=Qt&&"object"==typeof module&&module&&!module.nodeType&&module,Zt=Xt&&Xt.exports===Qt?u.Buffer:void 0,te=(Zt?Zt.isBuffer:void 0)||function(){return!1},ee={};ee["[object Float32Array]"]=ee["[object Float64Array]"]=ee["[object Int8Array]"]=ee["[object Int16Array]"]=ee["[object Int32Array]"]=ee["[object Uint8Array]"]=ee["[object Uint8ClampedArray]"]=ee["[object Uint16Array]"]=ee["[object Uint32Array]"]=!0,ee["[object Arguments]"]=ee["[object Array]"]=ee["[object ArrayBuffer]"]=ee["[object Boolean]"]=ee["[object DataView]"]=ee["[object Date]"]=ee["[object Error]"]=ee["[object Function]"]=ee["[object Map]"]=ee["[object Number]"]=ee["[object Object]"]=ee["[object RegExp]"]=ee["[object Set]"]=ee["[object String]"]=ee["[object WeakMap]"]=!1;var re,ne="object"==typeof exports&&exports&&!exports.nodeType&&exports,oe=ne&&"object"==typeof module&&module&&!module.nodeType&&module,ie=oe&&oe.exports===ne&&i.process,ae=function(){try{var t=oe&&oe.require&&oe.require("util").types;return t||ie&&ie.binding&&ie.binding("util")}catch(t){}}(),ue=ae&&ae.isTypedArray,ce=ue?(re=ue,function(t){return re(t)}):function(t){return _(t)&&Yt(t.length)&&!!ee[g(t)]};function se(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var fe=Object.prototype.hasOwnProperty;function le(t,e,r){var n=t[e];fe.call(t,e)&&rt(n,r)&&(void 0!==r||e in t)||xt(t,e,r)}var pe=/^(?:0|[1-9]\d*)$/;function he(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&pe.test(t))&&t>-1&&t%1==0&&t0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(Ee);function Ae(t,e){return $e(function(t,e,r){return e=Se(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,i=Se(n.length-e,0),a=Array(i);++o1?e[n-1]:void 0,i=n>2?e[2]:void 0;for(o=Te.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,e,r){if(!at(r))return!1;var n=typeof e;return!!("number"==n?Kt(r)&&he(e,r.length):"string"==n&&e in r)&&rt(r[e],t)}(e[0],e[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++r0))},sr=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var e=t.replace("array.<","").replace(">","");return e.indexOf("|")?e.split("|"):[e]}return!1},fr=function(t,e){var r=t.arg;return e.length>1?!r.filter((function(t){return!(e.length>e.filter((function(e){return!ur(e)(t)})).length)})).length:e.length>e.filter((function(t){return!cr(r,t)})).length},lr=function(t,e){if(void 0===e&&(e=null),S(t)){if(!e)return!0;if(cr(e))return!e.filter((function(e){var r=t[e.name];return!(e.type.length>e.type.filter((function(t){var e;return void 0===r||(!1!==(e=sr(t))?!fr({arg:r},e):!ur(t)(r))})).length)})).length}return!1},pr=function(t,e){var r,n,o,i,a;switch(!0){case"object"===t:return o=(n=e).arg,i=n.param,a=[o],Array.isArray(i.keys)&&i.keys.length&&a.push(i.keys),!Reflect.apply(lr,null,a);case"array"===t:return!cr(e.arg);case!1!==(r=sr(t)):return!fr(e,r);default:return!ur(t)(e.arg)}},hr=function(t,e){return void 0!==t?t:!0===e.optional&&void 0!==e.defaultvalue?e.defaultvalue:null},vr=function(t,e,r){var n;void 0===r&&(r=!1);var o=function(t,e){if(!cr(e))throw new Ie("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===e.length)return[];if(!cr(t))throw new Ie("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==e.length:return t.map((function(t,r){return{arg:t,index:r,param:e[r]}}));case!0===e[0].variable:var r=e[0].type;return t.map((function(t,n){return{arg:t,index:n,param:e[n]||{type:r,name:"_"}}}));case t.lengthe.length:var n=e.length,o=["any"];return t.map((function(t,r){var i=r>=n||!!e[r].optional,a=e[r]||{type:o,name:"_"+r};return{arg:i?hr(t,a):t,index:r,param:a,optional:i}}));default:throw new Be("Could not understand your arguments and parameter structure!",{args:t,params:e})}}(t,e),i=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var e=t.arg,r=t.param;return!!er(e)&&!(r.type.length>r.type.filter((function(e){return pr(e,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(e){return pr(e,t)})).length)}));return r?((n={}).error=i,n.data=o.map((function(t){return t.arg})),n):i},gr=d(Object.keys,Object),dr=Object.prototype.hasOwnProperty;function yr(t){return Kt(t)?ge(t):function(t){if(!It(t))return gr(t);var e=[];for(var r in Object(t))dr.call(t,r)&&"constructor"!=r&&e.push(r);return e}(t)}function _r(t,e){return t&&Nt(t,e,yr)}function br(t){var e=-1,r=null==t?0:t.length;for(this.__data__=new $t;++eu))return!1;var s=i.get(t);if(s&&i.get(e))return s==e;var f=-1,l=!0,p=2&r?new br:void 0;for(i.set(t,e),i.set(e,t);++f0;)e[r]=arguments[r+1];if(this.logger("($queue) get called"),!0===this.__suspend_state__){if(qn(this.__pattern__)){var n=this.__pattern__.test(t);if(!n)return!1}this.logger("($queue) added to $queue",e),this.queueStore.add([t].concat(e))}return!!this.__suspend_state__},Mn.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},Ln.prototype.__suspend__=function(t){if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value! we got "+typeof t);var e=this.__suspend_state__;this.__suspend_state__=t,this.logger('($suspend) Change from "'+e+'" --\x3e "'+t+'"'),!0===e&&!1===t&&this.__release__()},Ln.prototype.__release__=function(){var t=this,e=this.queueStore.size,r=this.__pattern__;if(this.__pattern__=null,this.logger("(release) was called with "+e+(r?' for "'+r+'"':"")+" item"+(e>1?"s":"")),e>0){var n=Array.from(this.queueStore);this.queueStore.clear(),this.logger("(release queue)",n),n.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}return e},Object.defineProperties(Ln.prototype,Mn);var Jn=function(t){function e(e){void 0===e&&(e={}),t.call(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={$name:{configurable:!0},is:{configurable:!0},$done:{configurable:!0}};return e.prototype.logger=function(){},r.$name.get=function(){return"to1source-event"},r.is.get=function(){return this.$name},e.prototype.$on=function(t,e,r){var n=this;void 0===r&&(r=null);this.validate(t,e);var o=this.takeFromStore(t);if(!1===o)return this.logger('($on) "'+t+'" is not in lazy store'),this.addToNormalStore(t,"on",e,r);this.logger("($on) "+t+" found in lazy store");var i=0;return o.forEach((function(o){var a=o[0],u=o[1],c=o[2];if(c&&"on"!==c)throw new Error(Nn+" "+c);n.logger("($on)",'call run "'+t+'"'),n.run(e,a,r||u),i+=n.addToNormalStore(t,"on",e,r||u)})),this.logger("($on) return size "+i),i},e.prototype.$once=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=this.takeFromStore(t);this.normalStore;if(!1===n)return this.logger('($once) "'+t+'" is not in the lazy store'),this.addToNormalStore(t,"once",e,r);this.logger("($once)",n);var o=Array.from(n)[0],i=o[0],a=o[1],u=o[2];if(u&&"once"!==u)throw new Error(Nn+" "+u);this.logger("($once)",'call run "'+t+'"'),this.run(e,i,r||a),this.$off(t)},e.prototype.$only=function(t,e,r){var n=this;void 0===r&&(r=null),this.validate(t,e);var o=!1,i=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger('($only) "'+t+'" add to normalStore'),o=this.addToNormalStore(t,"only",e,r)),!1!==i)&&(this.logger('($only) "'+t+'" found data in lazy store to execute'),Array.from(i).forEach((function(o){var i=o[0],a=o[1],u=o[2];if(u&&"only"!==u)throw new Error(Nn+" "+u);n.logger('($only) call run "'+t+'"'),n.run(e,i,r||a)})));return o},e.prototype.$onlyOnce=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=!1,o=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger('($onlyOnce) "'+t+'" add to normalStore'),n=this.addToNormalStore(t,"onlyOnce",e,r)),!1!==o){this.logger("($onlyOnce)",o);var i=Array.from(o)[0],a=i[0],u=i[1],c=i[2];if(c&&"onlyOnce"!==c)throw new Error(Nn+" "+c);this.logger('($onlyOnce) call run "'+t+'"'),this.run(e,a,r||u),this.$off(t)}return n},e.prototype.$replace=function(t,e,r,n){if(void 0===r&&(r=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,e),Reflect.apply(o,this,[t,e,r])}throw new Error(n+" is not supported!")},e.prototype.$trigger=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,i=this.normalStore;if(this.logger("($trigger) normalStore",i),i.has(t)){if(this.logger('($trigger) "'+t+'" found'),this.$queue(t,e,r,n))return this.logger('($trigger) Currently suspended "'+t+'" added to queue, nothing executed. Exit now.'),!1;for(var a=Array.from(i.get(t)),u=a.length,c=!1,s=0;s0;)n[o]=arguments[o+2];if(t.has(e)?(this.logger('(addToStore) "'+e+'" existed'),r=t.get(e)):(this.logger('(addToStore) create new Set for "'+e+'"'),r=new Set),n.length>2)if(Array.isArray(n[0])){var i=n[2];this.checkTypeInLazyStore(e,i)||r.add(n)}else this.checkContentExist(n,r)||(this.logger("(addToStore) insert new",n),r.add(n));else r.add(n);return t.set(e,r),[t,r.size]},e.prototype.checkContentExist=function(t,e){return!!Array.from(e).filter((function(e){return e[0]===t[0]})).length},e.prototype.checkTypeInStore=function(t,e){this.validateEvt(t,e);var r=this.$get(t,!0);return!1===r||!r.filter((function(t){var r=t[3];return e!==r})).length},e.prototype.checkTypeInLazyStore=function(t,e){this.validateEvt(t,e);var r=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",r),!!r&&!!Array.from(r).filter((function(t){return t[2]!==e})).length},e.prototype.addToNormalStore=function(t,e,r,n){if(void 0===n&&(n=null),this.logger('(addToNormalStore) try to add "'+e+'" --\x3e "'+t+'" to normal store'),this.checkTypeInStore(t,e)){this.logger("(addToNormalStore)",'"'+e+'" --\x3e "'+t+'" can add to normal store');var o=this.hashFnToKey(r),i=[this.normalStore,t,o,r,n,e],a=Reflect.apply(this.addToStore,this,i),u=a[0],c=a[1];return this.normalStore=u,c}return!1},e.prototype.addToLazyStore=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(e),r];n&&o.push(n);var i=Reflect.apply(this.addToStore,this,o),a=i[0],u=i[1];return this.lazyStore=a,this.logger("(addToLazyStore) size: "+u),u},e.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},r.normalStore.set=function(t){Cn.set(this,t)},r.normalStore.get=function(){return Cn.get(this)},r.lazyStore.set=function(t){Rn.set(this,t)},r.lazyStore.get=function(){return Rn.get(this)},e.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,e){return(t=(t<<5)-t+e.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(e.prototype,r),e}(Ln)),Un=function(t){function e(e){if("function"!=typeof e)throw new Error("Just die here the logger is not a function!");e("---\x3e Create a new EventEmitter <---"),t.call(this,{logger:e})}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(e.prototype,r),e}(Jn),Dn=function(t){var e=t.log,r=t.eventEmitter;return r?(e("eventEmitter is:",r.name),r):new Un(t.log)},In=function(t){var e=t.toLowerCase();return e.indexOf("http")>-1?e.indexOf("https")>-1?e.replace("https","wss"):e.replace("http","ws"):e},Bn=function(t,e,r){return[ze(t,e.loginHandlerName,(function(t){if(t&&kn(t))return e.log("Received __login__ with "+t),r.$trigger("__login__",[t]);throw new Ie(e.loginHandlerName,"Unexpected token "+t)})),e,r]},Wn=function(t,e,r){return[ze(t,e.logoutHandlerName,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__logout__",t)})),e,r]},Hn=function(t,e,r){return[Pe(t,"onLogin",(function(t){Z(t)&&r.$only("onLogin",t)})),e,r]};function Gn(t,e,r){return et(Bn,Wn,Hn)(t,e,r)}function Vn(t,e,r){K(t,"error")?r(t.error):K(t,"data")?e(t.data):r({message:"UKNNOWN RESULT!",error:t})}function Yn(t,e,r,n,o){void 0===n&&(n=[]);var i=Q(e,"emit_reply");return o("actionCall: "+i+" --\x3e "+r,n),t.$trigger(i,[r,V(n)]),new Promise((function(n,i){var a=Q(e,r,"onResult");t.$on(a,(function(t){o("got the first result",t),Vn(t,n,i)}))}))}var Kn,Qn,Xn,Zn=function(t,e,r,n,o,i){return Pe(t,"send",tt,(function(){return function(){for(var t=[],a=arguments.length;a--;)t[a]=arguments[a];return $n(t,o.params,!0).then((function(t){return i(r,n,t),Yn(e,r,n,t,_log)})).catch((function(t){i("send error",t),e.$call(Q(r,n,"onError"),[new Ie(n,t)])}))}}))},to=function(t,e,r,n,o,i){return[ze(t,"myNamespace",r),e,r,n,o,i]},eo=function(t,e,r,n,o,i){return[Pe(t,"onResult",(function(t){Z(t)&&e.$on(Q(r,n,"onResult"),(function(o){Vn(o,t,(function(t){i('Catch error: "'+n+'"',t),e.$trigger(Q(r,n,"onError"),t)}))}))})),e,r,n,o,i]},ro=function(t,e,r,n,o,i){return[Pe(t,"onMessage",(function(t){if(Z(t)){e.$only(Q(r,n,"onMessage"),(function(o){Vn(o,t,(function(t){i('Catch error: "'+n+'"',t),e.$trigger(Q(r,n,"onError"),t)}))}))}})),e,r,n,o,i]},no=function(t,e,r,n,o,i){return[Pe(t,"onError",(function(t){Z(t)&&e.$only(Q(r,n,"onError"),t)})),e,r,n,o,i]};function oo(t,e,r,n,o,i){var a=[to,eo,ro,no,Zn],u=Reflect.apply(et,null,a),c=[n,o,t,e,r,i];return Reflect.apply(u,null,c)}function io(t,e,r,n,o){return function(){for(var i=[],a=arguments.length;a--;)i[a]=arguments[a];return $n(i,n.params,!0).then((function(n){return Yn(t,e,r,n,o)})).catch(He)}}function ao(t,e,r){var n={},o=t.log;for(var i in r){var a=r[i];for(var u in a){var c=a[u];n=ze(n,u,oo(i,u,c,io(e,i,u,c,o),e,o))}}return[n,t,e,r]}function uo(t,e,r,n){return[Pe(t,"onError",(function(t){if(Z(t))for(var e in n)r.$on(Q(e,"onError"),t)})),e,r]}function co(t,e,r){return[Pe(t,"onReady",(function(t){Z(t)&&r.$only("onReady",t)})),e,r]}function so(t,e,r){var n=function(t,e,r){return ze(t,e.disconnectHandlerName,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__disconnect__",t)}))}(t,e,r);return e.log("---\x3e The final step to return the ws-client <---"),n.verifyEventEmitter=function(){return r.is},n.eventEmitter=e.eventEmitter,n.log=e.log,n}var fo=["roundtip","handshake"],lo={};lo.standalone=An(!1,["boolean"]),lo.debugOn=An(!1,["boolean"]),lo.loginHandlerName=An("login",["string"]),lo.logoutHandlerName=An("logout",["string"]),lo.disconnectHandlerName=An("disconnect",["string"]),lo.switchUserHandlerName=An("switch-user",["string"]),lo.hostname=An(!1,["string"]),lo.namespace=An("jsonql",["string"]),lo.wsOptions=An({},["object"]),lo.contract=An({},["object"],((Kn={}).checker=function(t){return!!function(t){return S(t)&&(K(t,"query")||K(t,"mutation")||K(t,"socket"))}(t)&&t},Kn)),lo.enableAuth=An(!1,["boolean"]),lo.token=An(!1,["string"]),lo.loginMethod=An("handshake",["string"],((Qn={}).enumv=fo,Qn)),lo.useJwt=An(!0,["boolean","string"]),lo.authStrKey=An(null,["string"]);var po={};po.serverType=An(null,["string"],((Xn={}).alias="socketClientType",Xn));var ho=Object.assign(lo,po),vo={log:null,eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:"",publicNamespace:"public",privateNamespace:"private"};function go(t){return Promise.resolve(t).then((function(t){return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new Ie(t)}}()),t.wssPath=In([t.hostname,t.namespace].join("/"),t.serverType),t.log=zn(t),t.eventEmitter=Dn(t),t}))}function yo(t){var e,r,n,o,i;return{opts:t,nspMap:(r=(e=t).contract,n=e.enableAuth,o=function(t){var e="jsonql";return t.enableAuth?[[e,t.privateNamespace].join("/"),[e,t.publicNamespace].join("/")]:[e]}(e),i=n?Qe(r):function(t,e){var r,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(r={},r[e]=n,r),publicNamespace:e}}(r.socket,o[0]),Object.assign(i,{namespaces:o})),ee:t.eventEmitter}}function _o(t){return function(e){return void 0===e&&(e={}),go(e).then(yo).then((function(t){return function(t,e,r){var n=[ao,co,uo];return t.enableAuth&&n.push(Gn),Reflect.apply(et,null,n)(t,r,e.nspGroup)}(t.opts,t.nspMap,t.ee)})).then((function(e){var r=e.opts,n=e.nspMap,o=e.ee;return t(r,n,o)})).then((function(t){return Reflect.apply(so,null,t)})).catch((function(t){console.error("jsonql-ws-core-client init error",t)}))}}function bo(t,e){var r=e.hostname,n=e.wssPath,o=e.wsOptions,i=e.nspClient,a=e.log,u=t?[r,t].join("/"):n;return a("createNspClient --\x3e ",u),i(u,o)}var mo=function(t,e,r,n){var o=n.log;r.$on("__logout__",(function(){var i=getPrivateNamespace(e);o("__logout__ event triggered"),function(t,e,r){e.forEach((function(e){t.$trigger(Q(e,"onError"),[{message:r,namespace:e}])}))}(r,[i],"__logout__"),o("logout from "+i),function(t,e){V(e).forEach((function(e){t.$off(Q(e,"emit_reply"))}))}(r,i),t[i]=null,notLoginWsListerner(i,r,n)}))};function jo(t,e){return function(r,n,o){var i=r.log,a=n.namespaces,u=function(t){return t.length>1&&t[0]}(a);return a.map((function(n){var c=u===n;if(i(n," --\x3e "+(c?"private":"public")+" nsp --\x3e ",!1!==e[n]),e[n]){i("[call bindWsHandler]",c,n);var s=[n,e[n],o,c,r];Reflect.apply(t,null,s)}else i("binding notLoginWsHandler to "+n),function(t,e,r){var n=r.log;e.$only(Q(t,"emit_reply"),(function(r,o){n("[notLoginListerner] hijack the ws call",t,r,o);var i={message:"NOT LOGIN"};e.$call(Q(t,r,"onError"),[i]),e.$call(Q(t,r,"onResult"),[{error:i}])}))}(n,o,r);return c&&(i("Has private and add logoutEvtHandler"),mo(e,a,o,r)),c}))}}function wo(t,e,r,n){var o=function(t,e){var r=Object.assign({},t,ho),n=Object.assign({},e,vo);return function(t){return Tn(t,r,n)}}(r,n);return function(r){return void 0===r&&(r={}),o(r).then((function(e){return t(e)})).then((function(t){var r=_o(e)(opts);return t.socket=r,t}))}}function Oo(t,e,r,n,o,i){t.onopen=function(){t.send(Ke("__intercom__",["__ping__",Ge()]))},t.onmessage=function(a){try{var u=tr(a.data);setTimeout((function(){t.terminate()}),50);var c=new e(r,Object.assign(i,u));n(c)}catch(t){o(t)}},t.onerror=function(t){o(t)}}function So(t,e,r){return new Promise((function(n,o){Oo(new t(e,r),t,e,n,o,r)}))}function Eo(t,e,r){return!1===e?function(e,n){void 0===n&&(n={});var o=In(e);return r("nspClient: \n"+o+"\n",n),So(t,o,n)}:function(e,n,o){void 0===o&&(o={});var i=In(e),a=n&&"string"==typeof n?i+"?token="+n:i;return r("nspAuthClient: \n"+a+"\n",o),So(t,a,o)}}var ko=Array.isArray,$o="object"==typeof o&&o&&o.Object===Object&&o,Ao="object"==typeof self&&self&&self.Object===Object&&self,To=$o||Ao||Function("return this")(),xo=To.Symbol,Po=Object.prototype,zo=Po.hasOwnProperty,No=Po.toString,Co=xo?xo.toStringTag:void 0;var Ro=Object.prototype.toString;var qo=xo?xo.toStringTag:void 0;function Fo(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":qo&&qo in Object(t)?function(t){var e=zo.call(t,Co),r=t[Co];try{t[Co]=void 0;var n=!0}catch(t){}var o=No.call(t);return n&&(e?t[Co]=r:delete t[Co]),o}(t):function(t){return Ro.call(t)}(t)}var Lo=function(t,e){return function(r){return t(e(r))}}(Object.getPrototypeOf,Object);function Mo(t){return null!=t&&"object"==typeof t}var Jo=Function.prototype,Uo=Object.prototype,Do=Jo.toString,Io=Uo.hasOwnProperty,Bo=Do.call(Object);function Wo(t){if(!Mo(t)||"[object Object]"!=Fo(t))return!1;var e=Lo(t);if(null===e)return!0;var r=Io.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&Do.call(r)==Bo}var Ho=function(t,e){void 0===e&&(e=!0);try{return JSON.parse(t)}catch(r){if(e)return t;throw new Error(r)}},Go=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return t.join("_")},Vo=function(t){return Ho("string"==typeof t?t:JSON.stringify(t))},Yo=function(){return!1};function Ko(t,e){return t===e||t!=t&&e!=e}function Qo(t,e){for(var r=t.length;r--;)if(Ko(t[r][0],e))return r;return-1}var Xo=Array.prototype.splice;function Zo(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1},Zo.prototype.set=function(t,e){var r=this.__data__,n=Qo(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};function ei(t){if(!ti(t))return!1;var e=Fo(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}var ri=To["__core-js_shared__"],ni=function(){var t=/[^.]+$/.exec(ri&&ri.keys&&ri.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}();var oi=Function.prototype.toString;var ii=/^\[object .+?Constructor\]$/,ai=Function.prototype,ui=Object.prototype,ci=ai.toString,si=ui.hasOwnProperty,fi=RegExp("^"+ci.call(si).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function li(t){return!(!ti(t)||function(t){return!!ni&&ni in t}(t))&&(ei(t)?fi:ii).test(function(t){if(null!=t){try{return oi.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function pi(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return li(r)?r:void 0}var hi=pi(To,"Map"),vi=pi(Object,"create");var gi=Object.prototype.hasOwnProperty;var di=Object.prototype.hasOwnProperty;function yi(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&t<=9007199254740991}function Ui(t){return null!=t&&Ji(t.length)&&!ei(t)}var Di="object"==typeof exports&&exports&&!exports.nodeType&&exports,Ii=Di&&"object"==typeof module&&module&&!module.nodeType&&module,Bi=Ii&&Ii.exports===Di?To.Buffer:void 0,Wi=(Bi?Bi.isBuffer:void 0)||function(){return!1},Hi={};Hi["[object Float32Array]"]=Hi["[object Float64Array]"]=Hi["[object Int8Array]"]=Hi["[object Int16Array]"]=Hi["[object Int32Array]"]=Hi["[object Uint8Array]"]=Hi["[object Uint8ClampedArray]"]=Hi["[object Uint16Array]"]=Hi["[object Uint32Array]"]=!0,Hi["[object Arguments]"]=Hi["[object Array]"]=Hi["[object ArrayBuffer]"]=Hi["[object Boolean]"]=Hi["[object DataView]"]=Hi["[object Date]"]=Hi["[object Error]"]=Hi["[object Function]"]=Hi["[object Map]"]=Hi["[object Number]"]=Hi["[object Object]"]=Hi["[object RegExp]"]=Hi["[object Set]"]=Hi["[object String]"]=Hi["[object WeakMap]"]=!1;var Gi="object"==typeof exports&&exports&&!exports.nodeType&&exports,Vi=Gi&&"object"==typeof module&&module&&!module.nodeType&&module,Yi=Vi&&Vi.exports===Gi&&$o.process,Ki=function(){try{var t=Vi&&Vi.require&&Vi.require("util").types;return t||Yi&&Yi.binding&&Yi.binding("util")}catch(t){}}(),Qi=Ki&&Ki.isTypedArray,Xi=Qi?function(t){return function(e){return t(e)}}(Qi):function(t){return Mo(t)&&Ji(t.length)&&!!Hi[Fo(t)]};function Zi(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var ta=Object.prototype.hasOwnProperty;function ea(t,e,r){var n=t[e];ta.call(t,e)&&Ko(n,r)&&(void 0!==r||e in t)||wi(t,e,r)}var ra=/^(?:0|[1-9]\d*)$/;function na(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&ra.test(t))&&t>-1&&t%1==0&&t0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(ga);function _a(t,e){return ya(function(t,e,r){return e=va(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,i=va(n.length-e,0),a=Array(i);++o1?r[o-1]:void 0,a=o>2?r[2]:void 0;for(i=t.length>3&&"function"==typeof i?(o--,i):void 0,a&&function(t,e,r){if(!ti(r))return!1;var n=typeof e;return!!("number"==n?Ui(r)&&na(e,r.length):"string"==n&&e in r)&&Ko(r[e],t)}(r[0],r[1],a)&&(i=o<3?void 0:i,o=1),e=Object(e);++n0;)e[r]=arguments[r+1];var n=Ge(),o=[t].concat(e);return o.push(n),Ke("__intercom__",o)}("__logout__")),log("terminate ws connection"),e.terminate()}catch(t){console.error("ws.terminate error",t)}}))};function Ta(t,e,r,n,o){var i=o.log,a=2;e.onopen=function(){i("=== ws.onopen listened --\x3e",t),r.$call("onReady")(t),0===--a&&r.$off("onReady"),n&&(i("isPrivate and fire the onLogin"),r.$call("onLogin")(t)),r.$only(Go(t,"emit_reply"),(function(t,r){var n=function(t,e,r){return void 0===e&&(e=[]),void 0===r&&(r=!1),JSON.stringify(Sa(t,e,r))}(t,r);i("ws.onopen.send",t,r,n),e.send(n)}))},e.onmessage=function(e){try{var n=function(t,e){void 0===e&&(e=Yo);try{var r,n=Vo(t);if(!1!==(r=ka(n)))return e("TS",n.TS),{data:Vo(r.__data__),resolverName:r.__event__,type:r.__reply__};throw new ja("payload can not decoded",t)}catch(t){return e("error",t)}}(e.data),o=n.resolverName,a=n.type;switch(i("Respond from server",a,n),a){case"emit_reply":var u=Go(t,o,"onMessage"),c=r.$trigger(u,[n]);i("EMIT_REPLY_TYPE",u,c);break;case"acknowledge_reply":var s=Go(t,o,"onResult"),f=r.$trigger(s,[n]);i("ACKNOWLEDGE_REPLY_TYPE",s,f);break;case"error":i("ERROR_KEY"),$a(r,t,o,n);break;default:i("Unhandled event!",n),$a(r,t,o,n)}}catch(e){console.error("ws.onmessage error",e),$a(r,t,!1,e)}},e.onclose=function(){i("ws.onclose callback")},e.onerror=function(e){i("ws.onerror",e),function(t,e,r){t.$trigger(Q(e,"onError"),[r])}(r,t,e)},n&&Aa(r,e)}var xa=function(t,e,r){var n,o,i=t.log,a=e.publicNamespace,u=e.namespaces;return i("createNspAction","publicNamespace",a,"namespaces",u),t.enableAuth?(n=u.map((function(e,n){return 0===n?r?(t.token=r,i("create createNspAuthClient at run time"),function(t,e){var r=e.hostname,n=e.wssPath,o=e.token,i=e.wsOptions,a=e.nspAuthClient,u=e.log,c=t?[r,t].join("/"):n;if(u("createNspAuthClient --\x3e",c),o&&"string"!=typeof o)throw new Error("Expect token to be string, but got "+o);return a(c,o,i)}(e,t)):Promise.resolve(!1):bo(e,t)})),void 0===o&&(o=!1),n.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===o?t.concat([e]):ba(t,e)}))}))}),Promise.resolve(!1===o?[]:Wo(o)?o:{}))).then((function(t){return t.map((function(t,e){var r;return(r={})[u[e]]=t,r})).reduce((function(t,e){return Object.assign(t,e)}),{})})):bo(!1,t).then((function(t){var e;return(e={})[a]=t,e}))};var Pa,za,Na=(Pa=e,function(t,e,r){var n=t.log;return t.nspClient=Eo(Pa,!1,n),t.nspAuthClient=Eo(Pa,!0,n),n("bindFrameworkToJsonql",r.name,e),function(t,e,r){var n=t.token;return xa(t,e,n).then((function(n){return jo(Ta,n)(t,e,r),t.enableAuth&&loginEventHandler(t,e,r),{opts:t,nspMap:e,ee:r}}))}(t,e,r)}),Ca=(za=Na,function(t,e,n){var o=Object.assign({},n,r);return wo(t,za,e,o)});exports.EventEmitterClass=Jn,exports.checkSocketClientType=function(t){return xn(t,po)},exports.createCombineWsClient=Ca,exports.getEventEmitter=Dn;
+"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t,e=(t=require("ws"))&&"object"==typeof t&&"default"in t?t.default:t,r={version:"version: 1.2.0 module: cjs-module",serverType:"ws"},n=Array.isArray,o="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},i="object"==typeof o&&o&&o.Object===Object&&o,a="object"==typeof self&&self&&self.Object===Object&&self,u=i||a||Function("return this")(),c=u.Symbol,s=Object.prototype,f=s.hasOwnProperty,l=s.toString,p=c?c.toStringTag:void 0;var h=Object.prototype.toString;var v=c?c.toStringTag:void 0;function g(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":v&&v in Object(t)?function(t){var e=f.call(t,p),r=t[p];try{t[p]=void 0;var n=!0}catch(t){}var o=l.call(t);return n&&(e?t[p]=r:delete t[p]),o}(t):function(t){return h.call(t)}(t)}function d(t,e){return function(r){return t(e(r))}}var y=d(Object.getPrototypeOf,Object);function _(t){return null!=t&&"object"==typeof t}var b=Function.prototype,m=Object.prototype,j=b.toString,w=m.hasOwnProperty,O=j.call(Object);function S(t){if(!_(t)||"[object Object]"!=g(t))return!1;var e=y(t);if(null===e)return!0;var r=w.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&j.call(r)==O}function E(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var i=Array(o);++n-1;);return r}(n,o),function(t,e){for(var r=t.length;r--&&P(e,t[r],0)>-1;);return r}(n,o)+1).join("")}var H=function(t){return n(t)?t:[t]},K=function(t,e){void 0===e&&(e=!0);try{return JSON.parse(t)}catch(r){if(e)return t;throw new Error(r)}},Y=function(t,e){try{var r=Object.keys(t);return n=e,!!r.filter((function(t){return t===n})).length}catch(t){return!1}var n},Q=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return t.join("_")},X=function(t){return K("string"==typeof t?t:JSON.stringify(t))},Z=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},tt=function(){return!1},et=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return Reflect.apply(e,null,H(t))}),Reflect.apply(t,null,r))}};function rt(t,e){return t===e||t!=t&&e!=e}function nt(t,e){for(var r=t.length;r--;)if(rt(t[r][0],e))return r;return-1}var ot=Array.prototype.splice;function it(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1},it.prototype.set=function(t,e){var r=this.__data__,n=nt(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};function ut(t){if(!at(t))return!1;var e=g(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}var ct,st=u["__core-js_shared__"],ft=(ct=/[^.]+$/.exec(st&&st.keys&&st.keys.IE_PROTO||""))?"Symbol(src)_1."+ct:"";var lt=Function.prototype.toString;function pt(t){if(null!=t){try{return lt.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var ht=/^\[object .+?Constructor\]$/,vt=Function.prototype,gt=Object.prototype,dt=vt.toString,yt=gt.hasOwnProperty,_t=RegExp("^"+dt.call(yt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function bt(t){return!(!at(t)||(e=t,ft&&ft in e))&&(ut(t)?_t:ht).test(pt(t));var e}function mt(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return bt(r)?r:void 0}var jt=mt(u,"Map"),wt=mt(Object,"create");var Ot=Object.prototype.hasOwnProperty;var St=Object.prototype.hasOwnProperty;function Et(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&t<=9007199254740991}function Yt(t){return null!=t&&Kt(t.length)&&!ut(t)}var Qt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Xt=Qt&&"object"==typeof module&&module&&!module.nodeType&&module,Zt=Xt&&Xt.exports===Qt?u.Buffer:void 0,te=(Zt?Zt.isBuffer:void 0)||function(){return!1},ee={};ee["[object Float32Array]"]=ee["[object Float64Array]"]=ee["[object Int8Array]"]=ee["[object Int16Array]"]=ee["[object Int32Array]"]=ee["[object Uint8Array]"]=ee["[object Uint8ClampedArray]"]=ee["[object Uint16Array]"]=ee["[object Uint32Array]"]=!0,ee["[object Arguments]"]=ee["[object Array]"]=ee["[object ArrayBuffer]"]=ee["[object Boolean]"]=ee["[object DataView]"]=ee["[object Date]"]=ee["[object Error]"]=ee["[object Function]"]=ee["[object Map]"]=ee["[object Number]"]=ee["[object Object]"]=ee["[object RegExp]"]=ee["[object Set]"]=ee["[object String]"]=ee["[object WeakMap]"]=!1;var re,ne="object"==typeof exports&&exports&&!exports.nodeType&&exports,oe=ne&&"object"==typeof module&&module&&!module.nodeType&&module,ie=oe&&oe.exports===ne&&i.process,ae=function(){try{var t=oe&&oe.require&&oe.require("util").types;return t||ie&&ie.binding&&ie.binding("util")}catch(t){}}(),ue=ae&&ae.isTypedArray,ce=ue?(re=ue,function(t){return re(t)}):function(t){return _(t)&&Kt(t.length)&&!!ee[g(t)]};function se(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var fe=Object.prototype.hasOwnProperty;function le(t,e,r){var n=t[e];fe.call(t,e)&&rt(n,r)&&(void 0!==r||e in t)||Nt(t,e,r)}var pe=/^(?:0|[1-9]\d*)$/;function he(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&pe.test(t))&&t>-1&&t%1==0&&t0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(Ee);function xe(t,e){return ke(function(t,e,r){return e=Se(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,i=Se(n.length-e,0),a=Array(i);++o1?e[n-1]:void 0,i=n>2?e[2]:void 0;for(o=Ae.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,e,r){if(!at(r))return!1;var n=typeof e;return!!("number"==n?Yt(r)&&he(e,r.length):"string"==n&&e in r)&&rt(r[e],t)}(e[0],e[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++r0))},sr=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var e=t.replace("array.<","").replace(">","");return e.indexOf("|")?e.split("|"):[e]}return!1},fr=function(t,e){var r=t.arg;return e.length>1?!r.filter((function(t){return!(e.length>e.filter((function(e){return!ur(e)(t)})).length)})).length:e.length>e.filter((function(t){return!cr(r,t)})).length},lr=function(t,e){if(void 0===e&&(e=null),S(t)){if(!e)return!0;if(cr(e))return!e.filter((function(e){var r=t[e.name];return!(e.type.length>e.type.filter((function(t){var e;return void 0===r||(!1!==(e=sr(t))?!fr({arg:r},e):!ur(t)(r))})).length)})).length}return!1},pr=function(t,e){var r,n,o,i,a;switch(!0){case"object"===t:return o=(n=e).arg,i=n.param,a=[o],Array.isArray(i.keys)&&i.keys.length&&a.push(i.keys),!Reflect.apply(lr,null,a);case"array"===t:return!cr(e.arg);case!1!==(r=sr(t)):return!fr(e,r);default:return!ur(t)(e.arg)}},hr=function(t,e){return void 0!==t?t:!0===e.optional&&void 0!==e.defaultvalue?e.defaultvalue:null},vr=function(t,e,r){var n;void 0===r&&(r=!1);var o=function(t,e){if(!cr(e))throw new Ie("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===e.length)return[];if(!cr(t))throw console.info(t),new Ie("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==e.length:return t.map((function(t,r){return{arg:t,index:r,param:e[r]}}));case!0===e[0].variable:var r=e[0].type;return t.map((function(t,n){return{arg:t,index:n,param:e[n]||{type:r,name:"_"}}}));case t.lengthe.length:var n=e.length,o=["any"];return t.map((function(t,r){var i=r>=n||!!e[r].optional,a=e[r]||{type:o,name:"_"+r};return{arg:i?hr(t,a):t,index:r,param:a,optional:i}}));default:throw new Be("Could not understand your arguments and parameter structure!",{args:t,params:e})}}(t,e),i=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var e=t.arg,r=t.param;return!!er(e)&&!(r.type.length>r.type.filter((function(e){return pr(e,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(e){return pr(e,t)})).length)}));return r?((n={}).error=i,n.data=o.map((function(t){return t.arg})),n):i},gr=d(Object.keys,Object),dr=Object.prototype.hasOwnProperty;function yr(t){return Yt(t)?ge(t):function(t){if(!It(t))return gr(t);var e=[];for(var r in Object(t))dr.call(t,r)&&"constructor"!=r&&e.push(r);return e}(t)}function _r(t,e){return t&&Ct(t,e,yr)}function br(t){var e=-1,r=null==t?0:t.length;for(this.__data__=new kt;++eu))return!1;var s=i.get(t);if(s&&i.get(e))return s==e;var f=-1,l=!0,p=2&r?new br:void 0;for(i.set(t,e),i.set(e,t);++f0){if(!1!==this.$get(t,!0)){var n=this.searchMapEvt(t);if(n.length){var o=n[0][3],i=(this.checkMaxStore(t,e),this);return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];var a=i.getMaxStore(t),u=-1;if(a>0){var c=i.$call(t,o,r);if(Reflect.apply(c,i,e),-1===(u=i.checkMaxStore(t)))return i.$off(t),-1}return u}}}return this.logger("The "+t+" is not registered, can not execute non-existing event at the moment"),-1}throw new Error("Expect max to be an integer and greater than zero! But we got ["+typeof e+"]"+e+" instead")},e.prototype.$replace=function(t,e,r,n){if(void 0===r&&(r=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,e),Reflect.apply(o,this,[t,e,r])}throw new Error(n+" is not supported!")},e.prototype.$trigger=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,i=this.normalStore;if(this.logger("($trigger) normalStore",i),i.has(t)){if(this.logger('($trigger) "'+t+'" found'),this.$queue(t,e,r,n))return this.logger('($trigger) Currently suspended "'+t+'" added to queue, nothing executed. Exit now.'),!1;for(var a=Array.from(i.get(t)),u=a.length,c=!1,s=0;s0&&--r,!(r>0))return this.maxCountStore.delete(t),this.logger("remove "+t+" from maxStore"),-1;this.maxCountStore.set(t,r)}return r}throw new Error("Expect max to be an integer, but we got "+typeof e+" "+e)},e.prototype.searchMapEvt=function(t){var e=this.$get(t,!0).filter((function(t){var e,r=t[3];return e=r,!!Rn.filter((function(t){return e===t})).length}));return e.length?e:[]},e.prototype.takeFromStore=function(t,e){void 0===e&&(e="lazyStore");var r=this[e];if(r){if(this.logger("(takeFromStore)",e,r),r.has(t)){var n=r.get(t);return this.logger('(takeFromStore) has "'+t+'"',n),r.delete(t),n}return!1}throw new Error('"'+e+'" is not supported!')},e.prototype.findFromStore=function(t,e,r){return void 0===r&&(r=!1),!!e.has(t)&&Array.from(e.get(t)).map((function(t){return r?t:t[1]}))},e.prototype.removeFromStore=function(t,e){return!!e.has(t)&&(this.logger("($off)",t),e.delete(t),!0)},e.prototype.getStoreSet=function(t,e){var r;return t.has(e)?(this.logger('(addToStore) "'+e+'" existed'),r=t.get(e)):(this.logger('(addToStore) create new Set for "'+e+'"'),r=new Set),r},e.prototype.addToStore=function(t,e){for(var r=[],n=arguments.length-2;n-- >0;)r[n]=arguments[n+2];var o=this.getStoreSet(t,e);if(r.length>2)if(Array.isArray(r[0])){var i=r[2];this.checkTypeInLazyStore(e,i)||o.add(r)}else this.checkContentExist(r,o)||(this.logger("(addToStore) insert new",r),o.add(r));else o.add(r);return t.set(e,o),[t,o.size]},e.prototype.checkContentExist=function(t,e){return!!Array.from(e).filter((function(e){return e[0]===t[0]})).length},e.prototype.checkTypeInStore=function(t,e){this.validateEvt(t,e);var r=this.$get(t,!0);return!1===r||!r.filter((function(t){var r=t[3];return e!==r})).length},e.prototype.checkTypeInLazyStore=function(t,e){this.validateEvt(t,e);var r=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",r),!!r&&!!Array.from(r).filter((function(t){return t[2]!==e})).length},e.prototype.addToNormalStore=function(t,e,r,n){if(void 0===n&&(n=null),this.logger('(addToNormalStore) try to add "'+e+'" --\x3e "'+t+'" to normal store'),this.checkTypeInStore(t,e)){this.logger("(addToNormalStore)",'"'+e+'" --\x3e "'+t+'" can add to normal store');var o=this.hashFnToKey(r),i=[this.normalStore,t,o,r,n,e],a=Reflect.apply(this.addToStore,this,i),u=a[0],c=a[1];return this.normalStore=u,c}return!1},e.prototype.addToLazyStore=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(e),r];n&&o.push(n);var i=Reflect.apply(this.addToStore,this,o),a=i[0],u=i[1];return this.lazyStore=a,this.logger("(addToLazyStore) size: "+u),u},e.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},r.normalStore.set=function(t){Ln.set(this,t)},r.normalStore.get=function(){return Ln.get(this)},r.lazyStore.set=function(t){Dn.set(this,t)},r.lazyStore.get=function(){return Dn.get(this)},Object.defineProperties(e.prototype,r),e}(function(t){function e(){t.call(this),this.__suspend_state__=null,this.__pattern__=null,this.queueStore=new Set}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={$queues:{configurable:!0}};return e.prototype.$suspend=function(){this.logger("---\x3e SUSPEND ALL OPS <---"),this.__suspend__(!0)},e.prototype.$release=function(){this.logger("---\x3e RELEASE SUSPENDED QUEUE <---"),this.__suspend__(!1)},e.prototype.$suspendEvent=function(t){var e=function(t){switch(!0){case!0===qn(t):return t;case!0===Mn(t):return new RegExp(t);default:return!1}}(t);if(qn(e))return this.__pattern__=e,this.$suspend();throw new Error('We expect a pattern variable to be string or RegExp, but we got "'+typeof e+'" instead')},e.prototype.$queue=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];if(this.logger("($queue) get called"),!0===this.__suspend_state__){if(qn(this.__pattern__)){var n=this.__pattern__.test(t);if(!n)return!1}this.logger("($queue) added to $queue",e),this.queueStore.add([t].concat(e))}return!!this.__suspend_state__},r.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},e.prototype.__suspend__=function(t){if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value! we got "+typeof t);var e=this.__suspend_state__;this.__suspend_state__=t,this.logger('($suspend) Change from "'+e+'" --\x3e "'+t+'"'),!0===e&&!1===t&&this.__release__()},e.prototype.__release__=function(){var t=this,e=this.queueStore.size,r=this.__pattern__;if(this.__pattern__=null,this.logger("(release) was called with "+e+(r?' for "'+r+'"':"")+" item"+(e>1?"s":"")),e>0){var n=Array.from(this.queueStore);this.queueStore.clear(),this.logger("(release queue)",n),n.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}return e},Object.defineProperties(e.prototype,r),e}(Jn))),Bn=function(t){function e(e){if("function"!=typeof e)throw new Error("Just die here the logger is not a function!");e("---\x3e Create a new EventEmitter <---"),t.call(this,{logger:e})}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(e.prototype,r),e}(In),Vn=function(t){var e=t.log,r=t.eventEmitter;return r?(e("eventEmitter is:",r.name),r):new Bn(t.log)},Wn=function(t){var e=t.toLowerCase();return e.indexOf("http")>-1?e.indexOf("https")>-1?e.replace("https","wss"):e.replace("http","ws"):e},Gn=function(t,e){H(e).forEach((function(e){t.$off(Q(e,"emit_reply"))}))};function Hn(t,e,r){Y(t,"error")?r(t.error):Y(t,"data")?Reflect.apply(e,null,[].concat(t.data)):r({message:"UKNNOWN RESULT!",error:t})}function Kn(t,e,r,n,o){void 0===n&&(n=[]);var i=Q(e,"emit_reply");return o("actionCall: "+i+" --\x3e "+r,n),t.$trigger(i,[r,H(n)]),new Promise((function(n,i){var a=Q(e,r,"onResult");t.$on(a,(function(t){o("got the first result",t),Hn(t,n,i)}))}))}var Yn=function(t,e,r,n,o,i){return Te(t,"send",tt,(function(){return i("running call getter method"),function(){for(var t=[],a=arguments.length;a--;)t[a]=arguments[a];return kn(t,o.params,!0).then((function(t){return i("execute send",r,n,t),Kn(e,r,n,t,i)})).catch((function(t){i("send error",t),e.$call(Q(r,n,"onError"),[new Ie(n,t)])}))}}))};function Qn(t,e,r,n,o){return function(){for(var i=[],a=arguments.length;a--;)i[a]=arguments[a];return kn(i,n.params,!0).then((function(n){return Kn(t,e,r,n,o)})).catch(We)}}var Xn=function(t,e,r,n,o,i){return[Pe(t,"myNamespace",r),e,r,n,o,i]},Zn=function(t,e,r,n,o,i){return[Te(t,"onResult",(function(t){Z(t)&&e.$on(Q(r,n,"onResult"),(function(o){Hn(o,t,(function(t){i('Catch error: "'+n+'"',t),e.$trigger(Q(r,n,"onError"),t)}))}))})),e,r,n,o,i]},to=function(t,e,r,n,o,i){return[Te(t,"onMessage",(function(t){if(Z(t)){e.$only(Q(r,n,"onMessage"),(function(o){i("onMessageCallback",o),Hn(o,t,(function(t){i('Catch error: "'+n+'"',t),e.$trigger(Q(r,n,"onError"),t)}))}))}})),e,r,n,o,i]},eo=function(t,e,r,n,o,i){return[Te(t,"onError",(function(t){Z(t)&&e.$only(Q(r,n,"onError"),t)})),e,r,n,o,i]};function ro(t,e,r,n,o,i){var a=[Xn,Zn,to,eo,Yn];return Reflect.apply(et,null,a)(n,o,t,e,r,i)}function no(t,e,r){var n=t.log,o={};for(var i in r){var a=r[i];for(var u in a){var c=a[u];o=Pe(o,u,ro(i,u,c,Qn(e,i,u,c,n),e,n))}}return[o,t,e,r]}function oo(t,e,r){return[Te(t,"onReady",(function(t){Z(t)&&r.$only("onReady",t)})),e,r]}function io(t,e,r,n){return[Te(t,"onError",(function(t){if(Z(t))for(var e in n)r.$on(Q(e,"onError"),t)})),e,r]}var ao,uo,co,so=function(t,e,r){return[Pe(t,e.loginHandlerName,(function(t){if(t&&$n(t))return e.log("Received __login__ with "+t),r.$trigger("__login__",[t]);throw new Ie(e.loginHandlerName,"Unexpected token "+t)})),e,r]},fo=function(t,e,r){return[Pe(t,e.logoutHandlerName,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__logout__",t)})),e,r]},lo=function(t,e,r){return[Te(t,"onLogin",(function(t){Z(t)&&r.$only("onLogin",t)})),e,r]};function po(t,e,r){return et(so,fo,lo)(t,e,r)}function ho(t,e,r){return(0,e.log)("[1] setupConnectPropKey"),[t=Pe(t,"connected",!1,!0),e,r]}function vo(t,e,r){var n=e.log;return n("[2] setupConnectEvtListener"),r.$on("__connect__",(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];n("setupConnectEvtListener pass and do nothing at the moment",t)})),[t,e,r]}function go(t,e,r){var n=e.log;return n("[3] setupConnectedEvtListener"),r.$on("__connected__",(function(){var e;t.connected=!0;var o=r.$release();return n("CONNECTED_EVENT_NAME",!0,"queue count",o),(e={}).connected=!0,e})),[t,e,r]}function yo(t,e,r){var n=e.log;return n("[4] setupDisconnectListener"),r.$on("__disconnect__",(function(){var e;return t.connected=!1,n("CONNECTED_EVENT_NAME",!1),(e={}).connected=!1,e})),[t,e,r]}function _o(t,e,r){var n=e.disconnectHandlerName;return(0,e.log)("[5] setupDisconectAction"),Pe(t,n,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__disconnect__",t)}))}function bo(t,e,r){var n=function(t,e,r){var n=[ho,vo,go,yo,_o];return Reflect.apply(et,null,n)(t,e,r)}(t,e,r);return n.verifyEventEmitter=function(){return r.is},n.eventEmitter=e.eventEmitter,n.log=e.log,r.$trigger("__connect__",[e,r]),!0===e.suspendOnStart&&e.$releaseNamespace(),n}var mo=["roundtip","handshake"],jo={};jo.standalone=xn(!1,["boolean"]),jo.debugOn=xn(!1,["boolean"]),jo.loginHandlerName=xn("login",["string"]),jo.logoutHandlerName=xn("logout",["string"]),jo.disconnectHandlerName=xn("disconnect",["string"]),jo.switchUserHandlerName=xn("switch-user",["string"]),jo.hostname=xn(!1,["string"]),jo.namespace=xn("jsonql",["string"]),jo.wsOptions=xn({},["object"]),jo.contract=xn({},["object"],((ao={}).checker=function(t){return!!function(t){return S(t)&&(Y(t,"query")||Y(t,"mutation")||Y(t,"socket"))}(t)&&t},ao)),jo.enableAuth=xn(!1,["boolean"]),jo.token=xn(!1,["string"]),jo.loginMethod=xn("handshake",["string"],((uo={}).enumv=mo,uo)),jo.useJwt=xn(!0,["boolean","string"]),jo.authStrKey=xn(null,["string"]),jo.suspendOnStart=xn(!1,["boolean"]);var wo={};wo.serverType=xn(null,["string"],((co={}).alias="socketClientType",co));var Oo=Object.assign(jo,wo),So={log:null,eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:"",publicNamespace:"public",privateNamespace:"private"};function Eo(t){return Promise.resolve(t).then((function(t){return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new Ie(t)}}()),t.wssPath=Wn([t.hostname,t.namespace].join("/"),t.serverType),t.log=Pn(t),t.eventEmitter=Vn(t),t}))}function $o(t){var e=function(t){var e=t.contract,r=t.enableAuth,n=function(t){var e="jsonql";return t.enableAuth?[[e,t.privateNamespace].join("/"),[e,t.publicNamespace].join("/")]:[e]}(t),o=r?Qe(e):function(t,e){var r,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(r={},r[e]=n,r),publicNamespace:e}}(e.socket,n[0]);return Object.assign(o,{namespaces:n})}(t),r=t.eventEmitter,n=t.log,o=e.namespaces;return n("namespaces",o),!0===t.suspendOnStart&&(t.$suspendNamepsace=function(){return o.forEach((function(t){return r.$suspendEvent(t)}))},t.$releaseNamespace=function(){return r.$release()},t.$suspendNamepsace()),{opts:t,nspMap:e,ee:r}}function ko(t){return function(e){return void 0===e&&(e={}),Eo(e).then($o).then((function(e){var r=e.opts,n=e.nspMap,o=e.ee;return t(r,n,o)})).then((function(t){return function(t,e,r){var n=[no,oo,io];return t.enableAuth&&n.push(po),n.push(bo),Reflect.apply(et,null,n)(t,r,e.nspGroup)}(t.opts,t.nspMap,t.ee)})).catch((function(t){console.error("[jsonql-ws-core-client init error]",t)}))}}function xo(t,e){var r=e.hostname,n=e.wssPath,o=e.wsOptions,i=e.nspClient,a=e.log,u=t?[r,t].join("/"):n;return a("createNspClient --\x3e ",u),i(u,o)}var Ao=function(t,e,r,n){var o=n.log;r.$on("__logout__",(function(){var i=getPrivateNamespace(e);o("__logout__ event triggered"),function(t,e,r){e.forEach((function(e){t.$trigger(Q(e,"onError"),[{message:r,namespace:e}])}))}(r,[i],"__logout__"),o("logout from "+i),Gn(r,i),t[i]=null,notLoginWsListerner(i,r,n)}))};function No(t,e){return function(r,n,o){var i=r.log,a=n.namespaces,u=function(t){return t.length>1&&t[0]}(a);return a.map((function(n){var c=u===n;if(i(n," --\x3e "+(c?"private":"public")+" nsp --\x3e ",!1!==e[n]),e[n]){i("[call bindWsHandler]",c,n);var s=[n,e[n],o,c,r];Reflect.apply(t,null,s)}else i("binding notLoginWsHandler to "+n),function(t,e,r){var n=r.log;e.$only(Q(t,"emit_reply"),(function(r,o){n("[notLoginListerner] hijack the ws call",t,r,o);var i={message:"NOT LOGIN"};e.$call(Q(t,r,"onError"),[i]),e.$call(Q(t,r,"onResult"),[{error:i}])}))}(n,o,r);return c&&(i("Has private and add logoutEvtHandler"),Ao(e,a,o,r)),c}))}}function To(t,e,r,n){var o=function(t,e){var r=Object.assign({},t,Oo),n=Object.assign({},e,So);return function(t){return An(t,r,n)}}(r,n);return function(r){return void 0===r&&(r={}),o(r).then((function(e){return t(e)})).then((function(t){var r=ko(e)(opts);return t.socket=r,t}))}}function Po(t,e,r,n,o,i){return t.onopen=function(){t.send(Ye("__intercom__",["__ping__",Ge()]))},t.onmessage=function(a){try{var u=tr(a.data);setTimeout((function(){t.terminate()}),50);var c=new e(r,Object.assign(i,u));n(c)}catch(t){o(t)}},t.onerror=function(t){o(t)},t}function Co(t,e,r){return new Promise((function(n,o){return Po(new t(e,r),t,e,n,o,r)}))}function zo(t,e,r){var n=r.log;return!1===e?function(e,r){void 0===r&&(r={});var o=Wn(e);return n("nspClient: \n"+o+"\n",r),Co(t,o,r)}:function(e,r,o){void 0===o&&(o={});var i=Wn(e),a=r&&"string"==typeof r?i+"?token="+r:i;return n("nspAuthClient: \n"+a+"\n",o),Co(t,a,o)}}var Ro="object"==typeof o&&o&&o.Object===Object&&o,qo="object"==typeof self&&self&&self.Object===Object&&self,Mo=Ro||qo||Function("return this")(),Fo=Mo.Symbol,Lo=Object.prototype,Do=Lo.hasOwnProperty,Jo=Lo.toString,Uo=Fo?Fo.toStringTag:void 0;var Io=Object.prototype.toString;var Bo=Fo?Fo.toStringTag:void 0;function Vo(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":Bo&&Bo in Object(t)?function(t){var e=Do.call(t,Uo),r=t[Uo];try{t[Uo]=void 0;var n=!0}catch(t){}var o=Jo.call(t);return n&&(e?t[Uo]=r:delete t[Uo]),o}(t):function(t){return Io.call(t)}(t)}var Wo=function(t,e){return function(r){return t(e(r))}}(Object.getPrototypeOf,Object);function Go(t){return null!=t&&"object"==typeof t}var Ho=Function.prototype,Ko=Object.prototype,Yo=Ho.toString,Qo=Ko.hasOwnProperty,Xo=Yo.call(Object);function Zo(t){if(!Go(t)||"[object Object]"!=Vo(t))return!1;var e=Wo(t);if(null===e)return!0;var r=Qo.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&Yo.call(r)==Xo}function ti(t,e){return t===e||t!=t&&e!=e}function ei(t,e){for(var r=t.length;r--;)if(ti(t[r][0],e))return r;return-1}var ri=Array.prototype.splice;function ni(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1},ni.prototype.set=function(t,e){var r=this.__data__,n=ei(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};function ii(t){if(!oi(t))return!1;var e=Vo(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}var ai=Mo["__core-js_shared__"],ui=function(){var t=/[^.]+$/.exec(ai&&ai.keys&&ai.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}();var ci=Function.prototype.toString;var si=/^\[object .+?Constructor\]$/,fi=Function.prototype,li=Object.prototype,pi=fi.toString,hi=li.hasOwnProperty,vi=RegExp("^"+pi.call(hi).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function gi(t){return!(!oi(t)||function(t){return!!ui&&ui in t}(t))&&(ii(t)?vi:si).test(function(t){if(null!=t){try{return ci.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function di(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return gi(r)?r:void 0}var yi=di(Mo,"Map"),_i=di(Object,"create");var bi=Object.prototype.hasOwnProperty;var mi=Object.prototype.hasOwnProperty;function ji(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&t<=9007199254740991}function Wi(t){return null!=t&&Vi(t.length)&&!ii(t)}var Gi="object"==typeof exports&&exports&&!exports.nodeType&&exports,Hi=Gi&&"object"==typeof module&&module&&!module.nodeType&&module,Ki=Hi&&Hi.exports===Gi?Mo.Buffer:void 0,Yi=(Ki?Ki.isBuffer:void 0)||function(){return!1},Qi={};Qi["[object Float32Array]"]=Qi["[object Float64Array]"]=Qi["[object Int8Array]"]=Qi["[object Int16Array]"]=Qi["[object Int32Array]"]=Qi["[object Uint8Array]"]=Qi["[object Uint8ClampedArray]"]=Qi["[object Uint16Array]"]=Qi["[object Uint32Array]"]=!0,Qi["[object Arguments]"]=Qi["[object Array]"]=Qi["[object ArrayBuffer]"]=Qi["[object Boolean]"]=Qi["[object DataView]"]=Qi["[object Date]"]=Qi["[object Error]"]=Qi["[object Function]"]=Qi["[object Map]"]=Qi["[object Number]"]=Qi["[object Object]"]=Qi["[object RegExp]"]=Qi["[object Set]"]=Qi["[object String]"]=Qi["[object WeakMap]"]=!1;var Xi="object"==typeof exports&&exports&&!exports.nodeType&&exports,Zi=Xi&&"object"==typeof module&&module&&!module.nodeType&&module,ta=Zi&&Zi.exports===Xi&&Ro.process,ea=function(){try{var t=Zi&&Zi.require&&Zi.require("util").types;return t||ta&&ta.binding&&ta.binding("util")}catch(t){}}(),ra=ea&&ea.isTypedArray,na=ra?function(t){return function(e){return t(e)}}(ra):function(t){return Go(t)&&Vi(t.length)&&!!Qi[Vo(t)]};function oa(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var ia=Object.prototype.hasOwnProperty;function aa(t,e,r){var n=t[e];ia.call(t,e)&&ti(n,r)&&(void 0!==r||e in t)||$i(t,e,r)}var ua=/^(?:0|[1-9]\d*)$/;function ca(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&ua.test(t))&&t>-1&&t%1==0&&t0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(ma);function Oa(t,e){return wa(function(t,e,r){return e=ba(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,i=ba(n.length-e,0),a=Array(i);++o1?r[o-1]:void 0,a=o>2?r[2]:void 0;for(i=t.length>3&&"function"==typeof i?(o--,i):void 0,a&&function(t,e,r){if(!oi(r))return!1;var n=typeof e;return!!("number"==n?Wi(r)&&ca(e,r.length):"string"==n&&e in r)&&ti(r[e],t)}(r[0],r[1],a)&&(i=o<3?void 0:i,o=1),e=Object(e);++n0;)e[r]=arguments[r+1];var n=Ge(),o=[t].concat(e);return o.push(n),Ye("__intercom__",o)}(LOGOUT_EVENT_NAME)),log("terminate ws connection"),e.terminate()}catch(t){console.error("ws.terminate error",t)}}))}var Fa=function(t,e,r,n){var o=[e];r&&o.push(r),o.push("onError");var i=Reflect.apply(ka,null,o),a=n.data||n;t.$trigger(i,[a])};function La(t,e,r,n,o){var i=o.log,a=2;return n&&(i("Private namespace",t," binding to the DISCONNECT ws.terminate"),Ma(r,e)),e.onopen=function(){i("=== ws.onopen listened --\x3e",t),r.$trigger("onReady",[t]),0===--a&&r.$off("onReady"),n&&(i("isPrivate and fire the onLogin"),r.$call("onLogin")(t)),r.$only(ka(t,"emit_reply"),(function(t,r){var n=function(t,e,r){return void 0===e&&(e=[]),void 0===r&&(r=!1),JSON.stringify(za(t,e,r))}(t,r);i("ws.onopen.send",t,r,n),e.send(n)}))},e.onmessage=function(e){i("ws.onmessage raw payload",e.data);try{var n=function(t,e){void 0===e&&(e=Aa);try{var r,n=xa(t);if(!1!==(r=qa(n)))return e("_data",r),{data:xa(r.__data__),resolverName:r.__event__,type:r.__reply__};throw new Ta("payload can not decoded",t)}catch(t){return e("error",t)}}(e.data),o=n.resolverName,a=n.type;switch(i("Respond from server",a,n),a){case"emit_reply":var u=ka(t,o,"onMessage"),c=r.$call(u)(n);i("EMIT_REPLY_TYPE",u,c);break;case"emit_acknowledge":var s=ka(t,o,"onResult"),f=r.$call(s)(n);i("ACKNOWLEDGE_REPLY_TYPE",s,f);break;case"error":i("ERROR_KEY"),Fa(r,t,o,n);break;default:i("Unhandled event!",n),Fa(r,t,o,n)}}catch(e){i("ws.onmessage error",e),Fa(r,t,!1,e)}},e.onclose=function(){i("ws.onclose callback")},e.onerror=function(e){i("ws.onerror",e),function(t,e,r){t.$trigger(Q(e,"onError"),[r])}(r,t,e)},e}var Da,Ja,Ua=(Da=e,function(t,e,r){var n=t.log;return n("There is problem here with passing the opts",t),t.nspClient=zo(Da,!1,t),t.nspAuthClient=zo(Da,!0,t),n("[1] bindWebsocketToJsonql",r.name,e),function(t,e,r){r("[2] setup the CONNECT_EVENT_NAME"),e.$only("__connect__",(function(e,n){return r("[3] CONNECT_EVENT_NAME",n),Ea(e,t).then((function(t){return No(La,t)})).then((function(r){return r(e,t,n)}))}))}(e,r,n),function(t,e,r){var n=t.log,o=e.namespaces;n("[4] loginEventHandler"),r.$only("__login__",(function(e){n("createClient LOGIN_EVENT_NAME $only handler"),Gn(r,o),t.token=e,r.$trigger("__connect__",[t,r])}))}(t,e,r),n("just before returing the values for the next operation from createClientBindingAction"),{opts:t,nspMap:e,ee:r}}),Ia=(Ja=Ua,function(t,e,n){var o=Object.assign({},n,r);return To(t,Ja,e,o)});exports.EventEmitterClass=In,exports.checkSocketClientType=function(t){return Nn(t,wo)},exports.createCombineWsClient=Ia,exports.getEventEmitter=Vn;
//# sourceMappingURL=node.js.map
diff --git a/packages/@jsonql/ws/node.js.map b/packages/@jsonql/ws/node.js.map
index d1486ce3485b15c09e4c9e3fb6fe8fffd1879806..712c46076e7cf2b8eec55df78edf3283dad5bf49 100644
--- a/packages/@jsonql/ws/node.js.map
+++ b/packages/@jsonql/ws/node.js.map
@@ -1 +1 @@
-{"version":3,"file":"node.js","sources":["../../ws-client-core/node_modules/lodash-es/_arraySome.js"],"sourcesContent":["/**\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"],"names":["SetCache"],"mappings":"yrxBAAAA"}
\ No newline at end of file
+{"version":3,"file":"node.js","sources":["../../ws-client-core/node_modules/lodash-es/_arraySome.js"],"sourcesContent":["/**\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"],"names":["SetCache"],"mappings":"uwxBAAAA"}
\ No newline at end of file
diff --git a/packages/@jsonql/ws/package.json b/packages/@jsonql/ws/package.json
index 47e21aa30c42f4e639c775a71febd381381eed6f..dd00fe3f5d4e38a6513fd846b1e7792cb8ede3ae 100644
--- a/packages/@jsonql/ws/package.json
+++ b/packages/@jsonql/ws/package.json
@@ -48,27 +48,26 @@
"license": "ISC",
"homepage": "jsonql.org",
"dependencies": {
- "jsonql-constants": "^2.0.7",
+ "jsonql-constants": "^2.0.14",
"jsonql-errors": "^1.2.1",
- "jsonql-jwt": "^1.3.10",
- "jsonql-params-validator": "^1.6.1",
- "jsonql-utils": "^1.2.4",
+ "jsonql-params-validator": "^1.6.2",
+ "jsonql-utils": "^1.2.6",
"jsonql-ws-client-core": "^0.9.0",
"ws": "^7.2.3"
},
"devDependencies": {
- "ava": "^3.5.0",
+ "ava": "^3.5.1",
"colors": "^1.4.0",
"esm": "^3.2.25",
"fs-extra": "^9.0.0",
"glob": "^7.1.6",
"jsonql-contract": "^1.9.1",
"jsonql-koa": "^1.6.2",
- "jsonql-ws-server": "^1.7.7",
+ "jsonql-ws-server": "^1.7.9",
"kefir": "^3.8.6",
"koa": "^2.11.0",
- "koa-bodyparser": "^4.2.1",
- "rollup": "^2.1.0",
+ "koa-bodyparser": "^4.3.0",
+ "rollup": "^2.2.0",
"rollup-plugin-alias": "^2.2.0",
"rollup-plugin-async": "^1.2.0",
"rollup-plugin-buble": "^0.19.8",
diff --git a/packages/@jsonql/ws/src/browser-ws-client.js b/packages/@jsonql/ws/src/browser-ws-client.js
index ec3757d03c29fd6fa10a35ab91e6f5dcc6450fc6..9a48139b64ed4ca3152fede7226f104744be6249 100644
--- a/packages/@jsonql/ws/src/browser-ws-client.js
+++ b/packages/@jsonql/ws/src/browser-ws-client.js
@@ -6,12 +6,12 @@ import {
import { wsClientConstProps } from './options'
-import frameworkSocketEngine from './core/framework-socket-engine'
+import setupSocketClientListener from './core/setup-socket-client-listener'
// export back the function and that's it
export default function wsBrowserClient(config = {}, constProps = {}) {
const initMethod = wsClientCore(
- frameworkSocketEngine,
+ setupSocketClientListener,
{},
Object.assign({}, wsClientConstProps, constProps)
)
diff --git a/packages/@jsonql/ws/src/core/create-websocket-binding/bind-framework-to-jsonql.js b/packages/@jsonql/ws/src/core/create-websocket-binding/bind-websocket-to-jsonql.js
similarity index 76%
rename from packages/@jsonql/ws/src/core/create-websocket-binding/bind-framework-to-jsonql.js
rename to packages/@jsonql/ws/src/core/create-websocket-binding/bind-websocket-to-jsonql.js
index 056874ebc90a01db55c22679238da6484d246a2f..cc0093c111bfcc4d47dbd14cca28cf015422900b 100644
--- a/packages/@jsonql/ws/src/core/create-websocket-binding/bind-framework-to-jsonql.js
+++ b/packages/@jsonql/ws/src/core/create-websocket-binding/bind-websocket-to-jsonql.js
@@ -11,24 +11,23 @@ import {
* @param {object} frameworkModule the different WebSocket module
* @return {function} the wsClientResolver
*/
-function bindFrameworkToJsonql(frameworkModule) {
+function bindWebsocketToJsonql(frameworkModule) {
/**
* wsClientResolver
* @param {object} opts configuration
* @param {object} nspMap from the contract
* @param {object} ee instance of the eventEmitter
- * @param {string} msg a message to id where the data coming from
* @return {object} passing the same 3 input out with additional in the opts
*/
- return function createClientBindingAction(opts, nspMap, ee, msg) {
+ return function createClientBindingAction(opts, nspMap, ee) {
const { log } = opts
- log(`Where the parameters coming from:`, msg)
+ log(`There is problem here with passing the opts`, opts)
- opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log)
- opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log)
+ opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, opts)
+ opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, opts, true)
// debug
- log(`[1] bindFrameworkToJsonql`, ee.name, nspMap)
+ log(`[1] bindWebsocketToJsonql`, ee.$name, nspMap)
// @2020-03-20 @NOTE
connectEventListener(nspMap, ee, log)
@@ -47,4 +46,4 @@ function bindFrameworkToJsonql(frameworkModule) {
}
}
-export { bindFrameworkToJsonql }
\ No newline at end of file
+export { bindWebsocketToJsonql }
\ No newline at end of file
diff --git a/packages/@jsonql/ws/src/core/create-websocket-binding/index.js b/packages/@jsonql/ws/src/core/create-websocket-binding/index.js
index d1ab0b8077eac7761aca505ef967adf90065e252..c859f222e81477dd43d412167ce1e85f510253fb 100644
--- a/packages/@jsonql/ws/src/core/create-websocket-binding/index.js
+++ b/packages/@jsonql/ws/src/core/create-websocket-binding/index.js
@@ -1,3 +1,3 @@
-import { bindFrameworkToJsonql } from './bind-framework-to-jsonql'
+import { bindWebsocketToJsonql } from './bind-websocket-to-jsonql'
-export default bindFrameworkToJsonql
\ No newline at end of file
+export default bindWebsocketToJsonql
\ No newline at end of file
diff --git a/packages/@jsonql/ws/src/core/create-websocket-binding/init-websocket-client.js b/packages/@jsonql/ws/src/core/create-websocket-binding/init-websocket-client.js
index d85ab996dad07b9e7b3fdb9bf30cfa1161de57ea..4194d9b55f183324823a5b3bf83f176bd8eac9f6 100644
--- a/packages/@jsonql/ws/src/core/create-websocket-binding/init-websocket-client.js
+++ b/packages/@jsonql/ws/src/core/create-websocket-binding/init-websocket-client.js
@@ -68,10 +68,12 @@ function asyncConnect(WebSocket, url, options) {
* therefore the object was pass as second parameter!
* @NOTE here we only return a method to create the client, it might not get call
* @param {object} WebSocket the client or node version of ws
- * @param {boolean} auth if it's auth then 3 param or just one
* @param {object} opts this is a breaking change we will init the client twice
+ * @param {boolean} [auth = false] if it's auth then 3 param or just one
+ * @return {function} the client method to connect to the ws socket server
*/
-function initWebSocketClient(WebSocket, auth, log) {
+function initWebSocketClient(WebSocket, opts, auth = false) {
+ const { log } = opts
if (auth === false) {
/**
* Create a non-protected client
diff --git a/packages/@jsonql/ws/src/core/framework-socket-engine.js b/packages/@jsonql/ws/src/core/setup-socket-client-listener.js
similarity index 100%
rename from packages/@jsonql/ws/src/core/framework-socket-engine.js
rename to packages/@jsonql/ws/src/core/setup-socket-client-listener.js
diff --git a/packages/@jsonql/ws/src/create-combine-client.js b/packages/@jsonql/ws/src/create-combine-client.js
index 5fa7ffe4e85001aca9caf1810a76cb50fa12f839..de8c45bfdec800f289588a7c132d886f7f3d37ef 100644
--- a/packages/@jsonql/ws/src/create-combine-client.js
+++ b/packages/@jsonql/ws/src/create-combine-client.js
@@ -14,12 +14,16 @@ import {
/**
* Overload the createCombineCreate to create a combine http / ws client
- * @param {object} configCheckMap
- * @param {object} constProps
+ * @param {object} frameworkSocketEngine
* @return {function} to accept config then generate the client
*/
function createCombineWsClientConstructor(frameworkSocketEngine) {
-
+ /**
+ * @param {object} httpClientConstructor
+ * @param {object} configCheckMap
+ * @param {object} constProps
+ * @return {object} the ws client combine with http client
+ */
return function createCombineWsClient(httpClientConstructor, configCheckMap, constProps) {
const localConstProps = Object.assign({}, constProps, wsClientConstProps)
diff --git a/packages/@jsonql/ws/src/node/module.js b/packages/@jsonql/ws/src/node/module.js
index aa8943983685ceabb2357f72ce9cdb630ec5f968..49dcd495a431021ca0dd9a402397ead4b04e121a 100644
--- a/packages/@jsonql/ws/src/node/module.js
+++ b/packages/@jsonql/ws/src/node/module.js
@@ -6,9 +6,9 @@ import {
getEventEmitter,
EventEmitterClass
} from '../create-combine-client'
-import nodeFrameworkSocketEngine from './node-framework-socket-engine'
+import setupSocketClientListener from './setup-socket-client-listener'
-const createCombineWsClient = createCombineWsClientConstructor(nodeFrameworkSocketEngine)
+const createCombineWsClient = createCombineWsClientConstructor(setupSocketClientListener)
export {
createCombineWsClient,
diff --git a/packages/@jsonql/ws/tests/ws-client-basic.test.js b/packages/@jsonql/ws/tests/ws-client-basic.test.js
index fb09c5b4edfec88432db235ce1af397d183f4434..0d807f466a9fdbfc5ace2f5e07d6c4d8b0a7319c 100644
--- a/packages/@jsonql/ws/tests/ws-client-basic.test.js
+++ b/packages/@jsonql/ws/tests/ws-client-basic.test.js
@@ -52,7 +52,7 @@ test.cb('It should able to connect to the ws server', t => {
}
})
-test.cb('It should able to handle error', t => {
+test.cb.skip('It should able to handle error', t => {
t.plan(1)
let client = t.context.client
@@ -66,7 +66,7 @@ test.cb('It should able to handle error', t => {
})
-test.cb('It should able to send message back while its talking to the server', t => {
+test.cb.skip('It should able to send message back while its talking to the server', t => {
let testCtn = 3
t.plan(testCtn)
diff --git a/packages/resolver/index.js b/packages/resolver/index.js
index d9c58368945ac6ead01c18835ab44018f0d0d5f6..ebc005a2892ea169979fafb05624317978cdcc97 100644
--- a/packages/resolver/index.js
+++ b/packages/resolver/index.js
@@ -11,7 +11,10 @@ const {
handleAuthMethods
} = require('./src/handle-auth-methods')
// added in 1.2.0
-const { getSocketInterceptor } = require('./src/get-socket-interceptor')
+const {
+ getSocketInterceptor,
+ getCacheSocketInterceptor
+} = require('./src/get-socket-interceptor')
// for 1.0.0 release (first on 0.9.8)
// we also export the node client generator parts
@@ -51,7 +54,8 @@ module.exports = {
getLocalValidator,
getSocketInterceptor,
-
+ getCacheSocketInterceptor,
+
executeResolver,
resolverRenderHandler,
// for node clients
diff --git a/packages/resolver/package.json b/packages/resolver/package.json
index 20361e3d103bfdf27c330f6b39bc947d78633df5..3795e59b68b0097e8351179a868711ce12b36911 100644
--- a/packages/resolver/package.json
+++ b/packages/resolver/package.json
@@ -1,6 +1,6 @@
{
"name": "jsonql-resolver",
- "version": "1.2.2",
+ "version": "1.2.4",
"description": "This is NOT for general use, please do not install it directly. This module is part of the jsonql tools supporting modules.",
"main": "index.js",
"files": [
@@ -34,13 +34,13 @@
"url": "https://gitee.com/to1source/jsonql/issues"
},
"dependencies": {
- "@jsonql/security": "^0.9.1",
+ "@jsonql/security": "^0.9.4",
"debug": "^4.1.1",
- "jsonql-constants": "^2.0.11",
+ "jsonql-constants": "^2.0.14",
"jsonql-errors": "^1.2.1",
"jsonql-node-client": "^1.3.1",
"jsonql-params-validator": "^1.6.2",
- "jsonql-utils": "^1.2.5",
+ "jsonql-utils": "^1.2.6",
"lodash.merge": "^4.6.2"
},
"devDependencies": {
diff --git a/packages/resolver/src/cache.js b/packages/resolver/src/cache.js
index 6cf044366cff6089fbef69d8afb41beaa2e37217..91f55f9bd3ab8ddab880732ad0d8b2fbe25af01d 100644
--- a/packages/resolver/src/cache.js
+++ b/packages/resolver/src/cache.js
@@ -10,7 +10,7 @@ therefore simply cache this part is not enough
*/
-const { isNodeCache } = require('@jsonql/security')
+const { isCacheObj } = require('@jsonql/security')
/**
* get it
@@ -19,9 +19,9 @@ const { isNodeCache } = require('@jsonql/security')
* @return {*} false when not found
*/
function getCacheResolver(key, store) {
- if (isNodeCache(store)) {
+ if (isCacheObj(store)) {
- return store.has(key) ? store.get(key) : false
+ return store.$has(key) ? store.$get(key) : false
}
return false
@@ -42,7 +42,7 @@ function cacheResolver(store) {
*/
return function cacheResolverAction(resolverName, resolver) {
// the set return true on success, then we return the resolver for use next
- return store.set(resolverName, resolver) ? resolver : false
+ return store.$set(resolverName, resolver) ? resolver : false
}
}
diff --git a/packages/resolver/src/combine-resolver.js b/packages/resolver/src/combine-resolver.js
index 1481eb3d162f386e3e05b8b36bfdcdbdd35d0321..588940b11d346170f3c65f56bcf53a95c3f44548 100644
--- a/packages/resolver/src/combine-resolver.js
+++ b/packages/resolver/src/combine-resolver.js
@@ -6,6 +6,7 @@ const { isString } = require('jsonql-params-validator')
const { getCacheResolver, cacheResolver } = require('./cache')
const { getResolver } = require('./resolve-methods')
+const debug = require('debug')('jsonql-resolver:combine-resolver')
/**
* this is a new feature that allow
@@ -31,9 +32,11 @@ function getCompleteSocketResolver(resolverName, opts, key = null, store = null)
let resolver
// [deliverFn, resolverName, args, opts, ws, userdata]
if (isString(key) && store !== null) {
+ debug('use cache resolver with key', key)
resolver = getCacheResolver(key, store)
if (resolver !== false) {
-
+ debug('return the cache version with key', key, resolver.toString())
+
return resolver
}
}
diff --git a/packages/resolver/src/get-socket-interceptor.js b/packages/resolver/src/get-socket-interceptor.js
index c14ece39f111011573a38e5e6374c9f63b131ecb..57e9d19e443ed093d78a3442ce4669b3e34761fe 100644
--- a/packages/resolver/src/get-socket-interceptor.js
+++ b/packages/resolver/src/get-socket-interceptor.js
@@ -16,9 +16,15 @@ const {
LOGOUT_FN_NAME_PROP_KEY,
DISCONNECT_FN_NAME_PROP_KEY
} = require('jsonql-constants')
-const { validateAsync } = require('jsonql-params-validator')
-const debug = require('debug')('jsonql-resolver:get-socket-interceptor')
+const { JsonqlResolverAppError, JsonqlResolverNotFoundError } = require('jsonql-errors')
+const { validateAsync, isString } = require('jsonql-params-validator')
+// const { isCacheObj } = require('@jsonql/security')
+
+const { getCacheResolver, cacheResolver } = require('./cache')
const { getFnBySourceType } = require('./search-resolvers')
+const { isFunc } = require('./utils')
+
+const debug = require('debug')('jsonql-resolver:get-socket-interceptor')
/**
* This is the first place to look to find the path to the interceptor
@@ -139,10 +145,30 @@ function getSocketInterceptor(evtName, opts) {
})
}
}
+ throw new JsonqlResolverNotFoundError('getSocketInterceptor', `${evtName} interceptor not found!`)
}
+/**
+ * Get the interceptor, cache it then call it again to return the cache version
+ * @param {string} evtName event name for the interceptor
+ * @param {object} opts configuration
+ * @param {string} key for storing the interceptor
+ * @param {object} store the cache store instance
+ * @return {function} the actual interceptor function
+ */
+function getCacheSocketInterceptor(evtName, opts, key, store) {
+ let resolverFn = getCacheResolver(key, store)
+ if (resolverFn && isFunc(resolverFn)) {
+ debug('return from cache')
+ return resolverFn
+ }
+ resolverFn = getSocketInterceptor(evtName, opts)
+
+ return cacheResolver(store)(key, resolverFn)
+}
module.exports = {
getSocketInterceptor,
- getSocketAuthInterceptorFn
+ getSocketAuthInterceptorFn,
+ getCacheSocketInterceptor
}
diff --git a/packages/resolver/src/utils.js b/packages/resolver/src/utils.js
index 2ed6b2ab423b74900d2318afeacf41e301fd37f1..e93d7a5603a4e4cae387848dc6edbec74b6668b3 100644
--- a/packages/resolver/src/utils.js
+++ b/packages/resolver/src/utils.js
@@ -65,7 +65,11 @@ const ctxErrorHandler = function(ctx, code, e, message = '') {
return render(ctx, packError(e, name, code, message))
}
+const isFunc = fun => typeof fun === 'function'
+
+
module.exports = {
+ isFunc,
getDebug,
handleOutput,
ctxErrorHandler
diff --git a/packages/resolver/tests/combine.test.js b/packages/resolver/tests/combine.test.js
index 27a33608f116bcb21228dab934709de9ad10e3a9..b72e1027c05eb3677f67e5bf2cf5287c20f72cd1 100644
--- a/packages/resolver/tests/combine.test.js
+++ b/packages/resolver/tests/combine.test.js
@@ -2,29 +2,37 @@
const test = require('ava')
const {
getCompleteSocketResolver,
- getCacheResolver
+ getCacheResolver,
+ getCacheSocketInterceptor
} = require('../index')
-const { isNodeCache, getNodeCache } = require('@jsonql/security')
+const { isCacheObj, getCache } = require('@jsonql/security')
const debug = require('debug')('jsonql-resolver:test:combine')
const fsx = require('fs-extra')
const { join } = require('path')
const { injectToFn, objHasProp } = require('jsonql-utils')
+const {
+ LOGIN_EVENT_NAME,
+ LOGIN_FN_NAME_PROP_KEY
+} = require('jsonql-constants')
+
test.before(t => {
- t.context.nodeCacheInstance = getNodeCache()
+ t.context.cacheInstance = getCache()
+
t.context.contract = fsx.readJsonSync(join(__dirname, 'fixtures', 'contract', 'contract.json'))
+ t.context.socketContract = fsx.readJsonSync(join(__dirname, 'fixtures', 'contract', 'socket', 'contract.json'))
})
test(`Testing the basic cache function first`, t => {
- const nodeCacheInstance = t.context.nodeCacheInstance
- const check = isNodeCache(nodeCacheInstance)
+
+ const check = isCacheObj(t.context.cacheInstance)
t.true(check)
})
test(`Test the nodeCache interface`, t => {
- const cache = t.context.nodeCacheInstance
- const result = cache.set('some-key', 'some-value')
+ const cache = t.context.cacheInstance
+ const result = cache.$set('some-key', 'some-value')
t.true(result)
})
@@ -35,7 +43,7 @@ test(`Test the getCompleteSocketResolver method`, t => {
resolverName,
{contract: t.context.contract},
resolverName,
- t.context.nodeCacheInstance
+ t.context.cacheInstance
]
const runInjectorsFn = Reflect.apply(getCompleteSocketResolver, null, args)
@@ -64,8 +72,9 @@ test(`Test the getCompleteSocketResolver method`, t => {
t.truthy(objHasProp(resolver, somekey))
t.is(resolver.timestamp, ts)
+ t.true(typeof resolver === 'function', 'resovler should be a function')
- const resolver1 = getCacheResolver(resolverName, t.context.nodeCacheInstance)
+ const resolver1 = getCacheResolver(resolverName, t.context.cacheInstance)
const msg = resolver1('la la la')
@@ -73,4 +82,25 @@ test(`Test the getCompleteSocketResolver method`, t => {
t.is(resolver1.timestamp, ts)
+ t.true(typeof resolver1 === 'function', 'retrieve cache function')
+
+})
+
+test(`testing the getSocketAuthInterceptor methods`, async t => {
+ const store = getCache()
+ const opts = {
+ contract: t.context.socketContract,
+ [LOGIN_FN_NAME_PROP_KEY]: 'login'
+ }
+
+ const login1 = getCacheSocketInterceptor(LOGIN_EVENT_NAME, opts, LOGIN_EVENT_NAME, store)
+
+ t.true(typeof login1 === 'function')
+
+ // t.is(await login1('1','2'), '12')
+
+ const login2 = getCacheSocketInterceptor(LOGIN_EVENT_NAME, opts, LOGIN_EVENT_NAME, store)
+
+ t.true(typeof login2 === 'function')
+
})
\ No newline at end of file
diff --git a/packages/resolver/tests/fixtures/contract/socket/contract.json b/packages/resolver/tests/fixtures/contract/socket/contract.json
index fdd392ce6536e1416efc780b957f9bd2d5b023f0..bbb3d99a198ad140c1260e79d9fb5d9a26981420 100644
--- a/packages/resolver/tests/fixtures/contract/socket/contract.json
+++ b/packages/resolver/tests/fixtures/contract/socket/contract.json
@@ -131,14 +131,14 @@
"returns": [
{
"type": [
- "boolean"
+ "string"
]
}
],
"params": [
{
"type": [
- "array."
+ "string"
],
"name": "args"
}
diff --git a/packages/resolver/tests/fixtures/resolvers/socket/auth/login.js b/packages/resolver/tests/fixtures/resolvers/socket/auth/login.js
index 37f11db04522d7bfe4aa5eea09c17709bd01fb23..da17639bd93bdbb18b1c696027c69c28c1ff8439 100644
--- a/packages/resolver/tests/fixtures/resolvers/socket/auth/login.js
+++ b/packages/resolver/tests/fixtures/resolvers/socket/auth/login.js
@@ -1,8 +1,8 @@
/**
* login interceptor
- * @param {array.} args
+ * @param {...string} args
* @return {boolean}
*/
module.exports = function login(...args) {
- return !!args.length
+ return args.join('')
}
diff --git a/packages/ws-client-core/index.js b/packages/ws-client-core/index.js
index b10f1977972ffb1a8c6fd1c0c932700b85f3f4d8..88cd9ce8f862fe81e58baf7a6c6a20190df4549e 100644
--- a/packages/ws-client-core/index.js
+++ b/packages/ws-client-core/index.js
@@ -56,6 +56,7 @@ export {
triggerNamespacesOnError,
handleNamespaceOnError,
+
fixWss,
clearMainEmitEvt,
diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json
index 7cb488d0f55802ba977cb21e5bb0f64a6d162e6f..083a8376d31bef45a3f728213fbfa0d7d81c9e47 100644
--- a/packages/ws-client-core/package.json
+++ b/packages/ws-client-core/package.json
@@ -56,7 +56,7 @@
},
"dependencies": {
"@to1source/event": "^1.1.1",
- "jsonql-constants": "^2.0.13",
+ "jsonql-constants": "^2.0.14",
"jsonql-errors": "^1.2.1",
"jsonql-params-validator": "^1.6.2",
"jsonql-utils": "^1.2.6"
diff --git a/packages/ws-client-core/src/api.js b/packages/ws-client-core/src/api.js
index dab593e32c8e3690e27a0d2aa0afa785e97efdd6..8b581403131fae8a4a05a048ebba39419a083c2e 100644
--- a/packages/ws-client-core/src/api.js
+++ b/packages/ws-client-core/src/api.js
@@ -26,7 +26,7 @@ export function wsClientCoreAction(setupSocketClientListener) {
return postCheckInjectOpts(config)
.then(createRequiredParams)
.then(
- ({opts, nspMap, ee}) => setupSocketClientListener(opts, nspMap, ee, 'jsonql-ws-client-core')
+ ({opts, nspMap, ee}) => setupSocketClientListener(opts, nspMap, ee)
)
.then(
({opts, nspMap, ee}) => callersGenerator(opts, nspMap, ee)
diff --git a/packages/ws-client-core/src/callers/setup-final-step.js b/packages/ws-client-core/src/callers/setup-final-step.js
index aae48fade4aa45db5f43c165fa99f30069a3b7a1..3780955bfd39f418c4c8688006e4c96e8318dbc3 100644
--- a/packages/ws-client-core/src/callers/setup-final-step.js
+++ b/packages/ws-client-core/src/callers/setup-final-step.js
@@ -1,6 +1,6 @@
// The final step of the setup before it returns the client
import { setupInterCom } from './setup-intercom'
-import { CONNECT_EVENT_NAME } from 'jsonql-constants'
+import { CONNECT_EVENT_NAME, SUSPEND_EVENT_PROP_KEY } from 'jsonql-constants'
/**
* The final step to return the client
@@ -23,7 +23,11 @@ function setupFinalStep(obj, opts, ee) {
// now at this point, we are going to call the connect event
ee.$trigger(CONNECT_EVENT_NAME, [opts, ee]) // just passing back the entire opts object
-
+ // also we can release the queue here
+ if (opts[SUSPEND_EVENT_PROP_KEY] === true) {
+ opts.$releaseNamespace()
+ }
+
return client
}
diff --git a/packages/ws-client-core/src/listener/event-listeners.js b/packages/ws-client-core/src/listener/event-listeners.js
index f5f548a8891733d568c28cf4d5d63a8c4d86b91b..bf3e7e7ff0efee4f30c7159c927fe1666295e1db 100644
--- a/packages/ws-client-core/src/listener/event-listeners.js
+++ b/packages/ws-client-core/src/listener/event-listeners.js
@@ -4,7 +4,8 @@ import {
NOT_LOGIN_ERR_MSG,
ON_ERROR_FN_NAME,
ON_RESULT_FN_NAME,
- DISCONNECT_EVENT_NAME
+ DISCONNECT_EVENT_NAME,
+ SUSPEND_EVENT_PROP_KEY
} from 'jsonql-constants'
import { EMIT_EVT, DISCONNECTED_ERROR_MSG } from '../options/constants'
import { createEvt, clearMainEmitEvt } from '../utils'
@@ -124,11 +125,3 @@ export const logoutEvtListener = (nsps, namespaces, ee, opts) => {
)
}
-/**
- * connect event listener this will not be a standalone one, instead
- * will combine with the client one, because this is to release the
- * $suspend
- */
-export const releaseEvtOnConnection = (nsps, namespaces, ee, opts) => {
- // @TODO
-}
\ No newline at end of file
diff --git a/packages/ws-client-core/src/listener/index.js b/packages/ws-client-core/src/listener/index.js
index 607741b4fdb8530e1a9f4f446aab945413944737..e66be28bad1298bdf3870283a25fd1a8c6b2853b 100644
--- a/packages/ws-client-core/src/listener/index.js
+++ b/packages/ws-client-core/src/listener/index.js
@@ -13,6 +13,7 @@ import {
handleNamespaceOnError
} from './trigger-namespaces-on-error'
+
// group all the import export in one place
export {
createNspClient,
diff --git a/packages/ws-client-core/src/listener/namespace-event-listener.js b/packages/ws-client-core/src/listener/namespace-event-listener.js
index 0a262c0fd9a166ebeb2cbea9629950806be19811..8d6b29453240ceac4136dd143d236b07f1d94bce 100644
--- a/packages/ws-client-core/src/listener/namespace-event-listener.js
+++ b/packages/ws-client-core/src/listener/namespace-event-listener.js
@@ -38,6 +38,8 @@ export function namespaceEventListener(bindSocketEventListener, nsps) {
// then we can use this prop to determine if we need to fire the ON_LOGIN_PROP_NAME event
const privateNamespace = getPrivateNamespace(namespaces)
+ // @TODO hook up the connectedEvtHandler somewhere
+
return namespaces.map(namespace => {
let isPrivate = privateNamespace === namespace
log(namespace, ` --> ${isPrivate ? 'private': 'public'} nsp --> `, nsps[namespace] !== false)
@@ -47,7 +49,7 @@ export function namespaceEventListener(bindSocketEventListener, nsps) {
let args = [namespace, nsps[namespace], ee, isPrivate, opts]
// Finally we binding everything together
Reflect.apply(bindSocketEventListener, null, args)
-
+
} else {
log(`binding notLoginWsHandler to ${namespace}`)
// a dummy placeholder
diff --git a/packages/ws-client-core/src/options/defaults.js b/packages/ws-client-core/src/options/defaults.js
index 8ca65838a861131be69cddcfdc0007242eecb80a..efc670d50dbbbdcff45eb5a09309137788c7ed06 100644
--- a/packages/ws-client-core/src/options/defaults.js
+++ b/packages/ws-client-core/src/options/defaults.js
@@ -33,6 +33,7 @@ import {
CONTRACT_PROP_KEY,
ENABLE_AUTH_PROP_KEY,
TOKEN_PROP_KEY,
+ SUSPEND_EVENT_PROP_KEY,
PUBLIC_KEY,
PRIVATE_KEY
@@ -72,7 +73,7 @@ const configCheckMap = {
// this is going to replace the use of useJwt === string next
authStrKey: createConfig(null, [STRING_TYPE]),
// this is experimental to see the effects, might take downlater
- suspendOnStart: createConfig(false, [BOOLEAN_TYPE])
+ [SUSPEND_EVENT_PROP_KEY]: createConfig(false, [BOOLEAN_TYPE])
}
// socket client
diff --git a/packages/ws-client-core/src/options/index.js b/packages/ws-client-core/src/options/index.js
index a5c0c568d50bac68b73be2f49bf369d9d2b796e4..9f277bf52dbe335dab175f77ca06cb0a843196b9 100644
--- a/packages/ws-client-core/src/options/index.js
+++ b/packages/ws-client-core/src/options/index.js
@@ -16,6 +16,10 @@ import {
getLogFn
} from '../utils'
+import {
+ SUSPEND_EVENT_PROP_KEY
+} from 'jsonql-constants'
+
/**
* We need this to find the socket server type
* @param {*} config
@@ -95,17 +99,16 @@ function createRequiredParams(opts) {
log(`namespaces`, namespaces)
// next we loop the namespace and suspend all the events prefix with namespace
- if (opts.suspendOnStart === true) {
+ if (opts[SUSPEND_EVENT_PROP_KEY] === true) {
// we create this as a function then we can call it again
opts.$suspendNamepsace = () => namespaces.forEach(namespace => ee.$suspendEvent(namespace))
// then we create a new method to releas the queue
// we prefix it with the $ to notify this is not a jsonql part methods
opts.$releaseNamespace = () => ee.$release()
-
// now run it
opts.$suspendNamepsace()
}
-
+
return { opts, nspMap, ee }
}
diff --git a/packages/ws-server-core/package.json b/packages/ws-server-core/package.json
index 4bab441f5253cbd8dc7349ffe4c80112336e2bfc..0e254b1a6d3e5a6c9b1d63d12920846dfd4dd846 100644
--- a/packages/ws-server-core/package.json
+++ b/packages/ws-server-core/package.json
@@ -1,6 +1,6 @@
{
"name": "jsonql-ws-server-core",
- "version": "0.8.2",
+ "version": "0.8.4",
"description": "This is the core module that drive the Jsonql WS Socket server, not for direct use.",
"main": "index.js",
"files": [
@@ -27,16 +27,16 @@
"author": "Joel Chu ",
"license": "MIT",
"dependencies": {
- "@jsonql/security": "^0.9.1",
+ "@jsonql/security": "^0.9.4",
"@to1source/event": "^1.1.1",
"colors": "^1.4.0",
"debug": "^4.1.1",
"esm": "^3.2.25",
"fs-extra": "^9.0.0",
- "jsonql-constants": "^2.0.13",
+ "jsonql-constants": "^2.0.14",
"jsonql-errors": "^1.2.1",
"jsonql-params-validator": "^1.6.2",
- "jsonql-resolver": "^1.2.2",
+ "jsonql-resolver": "^1.2.4",
"jsonql-utils": "^1.2.6",
"lodash": "^4.17.15"
},
@@ -55,7 +55,7 @@
"require": [
"esm"
],
- "cache": true,
+ "cache": false,
"concurrency": 5,
"failFast": true,
"failWithoutAssertions": false,
diff --git a/packages/ws-server-core/src/options/index.js b/packages/ws-server-core/src/options/index.js
index cc62c549f2b04156eb84199d6b1a68e6d107202c..6c04c1715855bf2eda4ab1a0e55b5a51b8c765c3 100644
--- a/packages/ws-server-core/src/options/index.js
+++ b/packages/ws-server-core/src/options/index.js
@@ -4,10 +4,6 @@ const { join } = require('path')
const fsx = require('fs-extra')
const { JsonqlValidationError } = require('jsonql-errors')
const { getNspInfoByConfig } = require('jsonql-utils')
-const {
- getNodeCache,
- isNodeCache
-} = require('@jsonql/security')
const {
checkConfig,
checkConfigAsync,
@@ -29,7 +25,7 @@ const {
socketAppProps
} = require('./props')
const { WsServerEventEmitter } = require('./event-emitter')
-
+const { getCache, isCacheObj } = require('@jsonql/security')
const debug = require('debug')('jsonql-ws-server-core:options')
@@ -59,9 +55,9 @@ function localCheckConfig(config) {
* @return {object} node cache instance
*/
function getCacheStore(opts) {
- return opts[CACHE_STORE_PROP_KEY] && isNodeCache(opts[CACHE_STORE_PROP_KEY])
+ return opts[CACHE_STORE_PROP_KEY] && isCacheObj(opts[CACHE_STORE_PROP_KEY])
? opts[CACHE_STORE_PROP_KEY]
- : getNodeCache()
+ : getCache()
}
/**
@@ -75,9 +71,7 @@ function initWsServerOption(config) {
// processing the key
.then(opts => {
const nspInfo = getNspInfoByConfig(opts)
-
- debug('take a look at nspInfo', nspInfo)
-
+ // debug('take a look at nspInfo', nspInfo)
// add a check here and make sure the nspInfo is correct
if (!nspInfo.publicNamespace) {
throw new JsonqlValidationError(`initWsServerOption`, nspInfo)
@@ -108,11 +102,12 @@ function initWsServerOption(config) {
/**
* This is a combine method that will check the options
* @param {object} config user supply
+ * @param {boolean} [init=false] this is mainly for internal test
* @return {object} promise resolve the opts
*/
-function wsServerCheckConfiguration(config) {
+function wsServerCheckConfiguration(config, init = false) {
return localCheckConfig(config)
- // .then(initWsServerOption)
+ .then(config => init ? initWsServerOption(config) : config)
}
// breaking change export as name also the options for merge with the upstream server
diff --git a/packages/ws-server-core/src/options/props.js b/packages/ws-server-core/src/options/props.js
index bbb4ad19c74ca0386f39f9101980ce9f8e5353fa..2d6d0f580d6e8d5f551bd675c0f1f264bd3cd532 100644
--- a/packages/ws-server-core/src/options/props.js
+++ b/packages/ws-server-core/src/options/props.js
@@ -77,7 +77,10 @@ const wsBaseOptions = {
allowOrgin: createConfig(['*'], [ARRAY_TYPE]),
serverInitOption: createConfig({}, [OBJECT_TYPE]),
// placeholder for now
- [CSRF_PROP_KEY]: createConfig('', [STRING_TYPE])
+ [CSRF_PROP_KEY]: createConfig('', [STRING_TYPE]),
+ // add this switch so we can test out the effects nodeCache is a fucking joke
+ // do not turn this on, because it can't store a complex object
+ enableCacheResolver: createConfig(true, [BOOLEAN_TYPE])
}
// we have to create a standlone prop to check if the user pass the socket server config first
diff --git a/packages/ws-server-core/src/resolver/resolve-socket-method.js b/packages/ws-server-core/src/resolver/resolve-socket-method.js
index cff9cd85edcfc9071acb4a2b88b9bc64a99d207c..eb175731d6b1289900b9ad0cf22b585de5387716 100644
--- a/packages/ws-server-core/src/resolver/resolve-socket-method.js
+++ b/packages/ws-server-core/src/resolver/resolve-socket-method.js
@@ -27,25 +27,34 @@ const resolveSocketMethod = function(
ws,
userdata) {
// resolverName, opts, key = null, store = null
- const key = [namespace, resolverName].join('-')
- const store = opts[CACHE_STORE_PROP_KEY]
+ const _params = [resolverName, opts]
- const actionFn = getCompleteSocketResolver(resolverName, opts, key, store)
+ if (opts.enableCacheResolver === true) {
+ const key = [namespace, resolverName].join('-')
+ const store = opts[CACHE_STORE_PROP_KEY]
+ _params.push(key, store)
+ }
+
+ const actionFn = Reflect.apply(getCompleteSocketResolver, null, _params)
const injectorFns = getInjectors()
const params = [ deliverFn, resolverName, ws, userdata, opts ]
- return Promise.resolve(actionFn(injectorFns, params))
- .then(resolver => {
- try {
- return Reflect.apply(resolver, null, args)
- } catch(err) {
- debug('Error happen here in side the resolveSocketMethod', err)
- // it's not nice, but we catch error here then we won't affect
- // other error like validation error might get throw earlier in the process
- throw new JsonqlResolverAppError(resolverName, err)
- }
- })
+ return new Promise((resolver, rejecter) => {
+ try {
+ const resolverFn = actionFn(injectorFns, params)
+ debug('resolveSocketMethod resolver', typeof resolverFn, resolverFn, args)
+
+ // this is still wrong, why are we not running it throught the validator?
+
+ resolver( Reflect.apply(resolverFn, null, args) )
+ } catch(err) {
+ debug('Error happen here in side the resolveSocketMethod', err)
+ // it's not nice, but we catch error here then we won't affect
+ // other error like validation error might get throw earlier in the process
+ rejecter(new JsonqlResolverAppError(resolverName, err))
+ }
+ })
}
// we only need to export one method
diff --git a/packages/ws-server-core/tests/fixtures/contract.json b/packages/ws-server-core/tests/fixtures/contract.json
index dd3a5ef6af6889271a1fbde197e61020f781b1ab..29aa176df6d669547554fab76a8f31cda4b37214 100644
--- a/packages/ws-server-core/tests/fixtures/contract.json
+++ b/packages/ws-server-core/tests/fixtures/contract.json
@@ -5,7 +5,7 @@
"timestamp": 1559136905329,
"socket": {
"causeError": {
- "file": "/home/joel/projects/open-source/jsonqltools/packages/ws-server/tests/fixtures/resolvers/socket/cause-error.js",
+ "file": "/home/joel/projects/open-source/jsonql/packages/ws-server-core/tests/fixtures/resolvers/socket/cause-error.js",
"event": "cause-error",
"description": false,
"params": [
@@ -27,7 +27,7 @@
]
},
"chatroom": {
- "file": "/home/joel/projects/open-source/jsonqltools/packages/ws-server/tests/fixtures/resolvers/socket/chatroom.js",
+ "file": "/home/joel/projects/open-source/jsonql/packages/ws-server-core/tests/fixtures/resolvers/socket/chatroom.js",
"event": "chatroom",
"description": false,
"params": [
@@ -56,7 +56,7 @@
]
},
"delayFn": {
- "file": "/home/joel/projects/open-source/jsonqltools/packages/ws-server/tests/fixtures/resolvers/socket/delay-fn.js",
+ "file": "/home/joel/projects/open-source/jsonql/packages/ws-server-core/tests/fixtures/resolvers/socket/delay-fn.js",
"event": "delay-fn",
"description": false,
"params": [
@@ -78,7 +78,7 @@
"returns": false
},
"wsHandler": {
- "file": "/home/joel/projects/open-source/jsonqltools/packages/ws-server/tests/fixtures/resolvers/socket/ws-handler.js",
+ "file": "/home/joel/projects/open-source/jsonql/packages/ws-server-core/tests/fixtures/resolvers/socket/ws-handler.js",
"event": "ws-handler",
"description": "method just for testing the ws",
"params": [
diff --git a/packages/ws-server-core/tests/fixtures/resolvers/socket/chatroom.js b/packages/ws-server-core/tests/fixtures/resolvers/socket/chatroom.js
index 0b57676e1e3a1cd3ee583eaaf249a9accea26ce6..78301e799c975ef23b643dc7eee9f4de7e239435 100644
--- a/packages/ws-server-core/tests/fixtures/resolvers/socket/chatroom.js
+++ b/packages/ws-server-core/tests/fixtures/resolvers/socket/chatroom.js
@@ -7,6 +7,6 @@
* @return {string} reply
*/
module.exports = function(msg, timestamp) {
- const d = Date.now() - timestamp;
- return msg + ` took ${d} ms`;
+ const d = Date.now() - (timestamp || 0)
+ return msg + ` took ${d} ms`
}
diff --git a/packages/ws-server-core/tests/fn.test.js b/packages/ws-server-core/tests/fn.test.js
index 2c0a5d45b55e47d5e40e71f30dfc0a146b0a705e..002e11a63834bed4b15a906d50a973ba60ecbe30 100644
--- a/packages/ws-server-core/tests/fn.test.js
+++ b/packages/ws-server-core/tests/fn.test.js
@@ -1,18 +1,25 @@
const test = require('ava')
const { handleInterCom } = require('../src/handles/handle-intercom')
-const { getNodeCache } = require('@jsonql/security')
-// const getNodeCache = require('../src/share/get-node-cache')
-
+const { getCache } = require('@jsonql/security')
+// const fsx = require('fs-extra')
+const { join } = require('path')
const debug = require('debug')('jsonql-ws-core:test:fn')
const {
SOCKET_PING_EVENT_NAME,
CACHE_STORE_PROP_KEY
} = require('jsonql-constants')
+const { resolveSocketMethod } = require('../src/resolver/resolve-socket-method')
+const {
+ wsServerCheckConfiguration
+} = require('../src/options')
+
+
+
test.cb(`Just testing the handleInterCom function interface`, t => {
t.plan(2)
const config = {
- [CACHE_STORE_PROP_KEY]: getNodeCache()
+ [CACHE_STORE_PROP_KEY]: getCache()
}
const ws = {}
const deliverFn = function(...args) {
@@ -35,4 +42,38 @@ test.cb(`Just testing the handleInterCom function interface`, t => {
t.end()
}, 100)
-})
\ No newline at end of file
+})
+
+
+test.only(`test the get-socket-resolver method mainly to look at the cache`, async t => {
+ const opts = {
+ contractDir: join(__dirname, 'fixtures'),
+ resolverDir: join(__dirname, 'fixtures', 'resolvers')
+ }
+ const config = await wsServerCheckConfiguration(opts, true)
+ const callbackFn = (str) => {
+ console.info(str)
+ }
+
+ const _params = [
+ 'jsonql',
+ 'chatroom',
+ callbackFn,
+ ['na na na', Date.now()], // this is the clean value from validateAsync
+ config,
+ {},
+ false
+ ]
+
+ const result1 = await Reflect.apply(resolveSocketMethod, null, _params)
+
+ t.truthy(result1)
+
+ // call it again
+
+ const result2 = await Reflect.apply(resolveSocketMethod, null, _params)
+
+ // debug(resolver1.toString())
+ t.truthy(result2)
+
+})
diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json
index fa5d0b065aa0b031a316ab75a0ceefc3b1fa0133..76dae9ae7a969a55cdb7deeac6278bbb094f0da7 100755
--- a/packages/ws-server/package.json
+++ b/packages/ws-server/package.json
@@ -1,6 +1,6 @@
{
"name": "jsonql-ws-server",
- "version": "1.7.9",
+ "version": "1.7.10",
"description": "Setup WebSocket server for the jsonql to run on the same host, automatic generate public / private channel using contract",
"main": "index.js",
"files": [
@@ -33,9 +33,9 @@
"dependencies": {
"colors": "^1.4.0",
"debug": "^4.1.1",
- "jsonql-constants": "^2.0.13",
+ "jsonql-constants": "^2.0.14",
"jsonql-utils": "^1.2.6",
- "jsonql-ws-server-core": "^0.8.2",
+ "jsonql-ws-server-core": "^0.8.3",
"ws": "^7.2.3"
},
"devDependencies": {
diff --git a/packages/ws-server/src/index.js b/packages/ws-server/src/index.js
index fd314f782644536af8be83f4560c3d8a9f34d850..55bcd83322b8c964b215152a9df84436fca6df85 100644
--- a/packages/ws-server/src/index.js
+++ b/packages/ws-server/src/index.js
@@ -26,7 +26,10 @@ function jsonqlWsServerAction(opts, server) {
* @return {mixed} return the undelying socket server instance for further use
*/
function jsonqlWsServer(config, server) {
- // @TODO check the options
+ // @TODO when this is using the standalone mode
+ // we should just init the http.createServer instead of expecting to pass
+ // the server
+
const setupFn = jsonqlWsServerCore(setupSocketServer)
return setupFn(config, server)
}