From df43f6718c2cd933d004a6716c5c72559e2cf6b7 Mon Sep 17 00:00:00 2001 From: joelchu Date: Mon, 16 Mar 2020 20:57:30 +0800 Subject: [PATCH 01/66] complete the changes for nsp clients --- packages/@jsonql/ws/package.json | 4 ++-- .../bind-framework-to-jsonql.js | 23 +++---------------- .../init-websocket-client.js | 14 +++++------ 3 files changed, 12 insertions(+), 29 deletions(-) diff --git a/packages/@jsonql/ws/package.json b/packages/@jsonql/ws/package.json index d539adee..b7633305 100644 --- a/packages/@jsonql/ws/package.json +++ b/packages/@jsonql/ws/package.json @@ -48,7 +48,7 @@ "license": "ISC", "homepage": "jsonql.org", "dependencies": { - "jsonql-constants": "^2.0.2", + "jsonql-constants": "^2.0.4", "jsonql-errors": "^1.2.1", "jsonql-jwt": "^1.3.10", "jsonql-params-validator": "^1.6.1", @@ -64,7 +64,7 @@ "glob": "^7.1.6", "jsonql-contract": "^1.8.10", "jsonql-koa": "^1.6.2", - "jsonql-ws-server": "^1.7.3", + "jsonql-ws-server": "^1.7.4", "kefir": "^3.8.6", "koa": "^2.11.0", "koa-bodyparser": "^4.2.1", 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-framework-to-jsonql.js index 1b5216a7..1d8880c5 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-framework-to-jsonql.js @@ -1,17 +1,7 @@ // share method to create the wsClientResolver import { initWebSocketClient } from './init-websocket-client' import createNsp from '../create-nsp' - -/** - * This will decided how many clients we need to create based on the enableAuth - * @param {object} frameworkModule WebSocket - * @param {object} opts configuration - * @return {promise} resolve the opts with the newly created clients - */ -function createNspClients(frameworkModule, opts) { - -} - +import { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants' /** * Create the framework <---> jsonql client binding @@ -19,11 +9,6 @@ function createNspClients(frameworkModule, opts) { * @return {function} the wsClientResolver */ function bindFrameworkToJsonql(frameworkModule) { - // @NOTE this will be a breaking change - // the result will be a promise instead of just a normal client - const nspClient = initWebSocketClient(frameworkModule) - const nspAuthClient = initWebSocketClient(frameworkModule, true) - /** * wsClientResolver * @param {object} opts configuration @@ -33,10 +18,8 @@ function bindFrameworkToJsonql(frameworkModule) { */ return function createClientBindingAction(opts, nspMap, ee) { - - - opts.nspClient = nspClient - opts.nspAuthClient = nspAuthClient + opts[NSP_CLIENT] = initWebSocketClient(frameworkModule) + opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true) // @1.0.7 remove later once everything fixed const { log } = opts log(`bindFrameworkToJsonql`, ee.name, nspMap) 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 182e8aea..624eeac1 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 @@ -5,7 +5,7 @@ import { fixWss } from '../modules' import { createInitPing, extractPingResult -} from './modules' +} from '../modules' /** * Group the ping and get respond create new client in one @@ -17,8 +17,7 @@ import { * @param {boolean} auth client or not * @return {promise} resolve the confirm client */ -function initPingAction(ws, WebSocket, url, resolver, rejecter, auth) { - const name = auth ? 'nspAuthClient' : 'nspClient' +function initPingAction(ws, WebSocket, url, resolver, rejecter) { // @TODO how to we id this client can issue a CSRF // by origin? ws.onopen = function onOpenCallback() { @@ -31,7 +30,7 @@ function initPingAction(ws, WebSocket, url, resolver, rejecter, auth) { // terminate the client ws.terminate() // return the new one with csrf header - resolver({[name]: new WebSocket(url, header)}) + resolver(new WebSocket(url, header)) } catch(e) { rejecter(e) } @@ -45,11 +44,12 @@ function initPingAction(ws, WebSocket, url, resolver, rejecter, auth) { /** * The bug was in the wsOptions where ws don't need it but socket.io do * 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 */ -function initWebSocketClient(WebSocket, auth = false, opts = {}) { +function initWebSocketClient(WebSocket, auth = false) { if (auth === false) { /** * Create a non-protected client @@ -61,7 +61,7 @@ function initWebSocketClient(WebSocket, auth = false, opts = {}) { return new Promise((resolver, rejecter) => { const _url = fixWss(url) const unconfirmClient = new WebSocket(_url) - initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, auth) + initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter) }) } } @@ -79,7 +79,7 @@ function initWebSocketClient(WebSocket, auth = false, opts = {}) { return new Promise((resolver, rejecter) => { const unconfirmClient = new WebSocket(_url) - initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, auth) + initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter) }) } } -- Gitee From 8bd120a8d6879a526a2ee02ca73bc0a4657cdea3 Mon Sep 17 00:00:00 2001 From: joelchu Date: Mon, 16 Mar 2020 21:12:09 +0800 Subject: [PATCH 02/66] Add back the wsOptions parameter to the init nsp client --- .../src/core/create-nsp/create-nsp-action.js | 4 +++- .../init-websocket-client.js | 18 ++++++++++-------- packages/ws-client-core/package.json | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/@jsonql/ws/src/core/create-nsp/create-nsp-action.js b/packages/@jsonql/ws/src/core/create-nsp/create-nsp-action.js index ca9727e5..c2f55c95 100644 --- a/packages/@jsonql/ws/src/core/create-nsp/create-nsp-action.js +++ b/packages/@jsonql/ws/src/core/create-nsp/create-nsp-action.js @@ -9,12 +9,14 @@ import { * @param {object} opts configuration * @param {object} nspMap from contract * @param {string|null} token whether we have the token at run time - * @return {object} nsps namespace with namespace as key + * @return {promise} resolve the nsps namespace with namespace as key */ const createNspAction = function(opts, nspMap, token) { const { log } = opts let { publicNamespace, namespaces } = nspMap log(`createNspAction`, 'publicNamespace', publicNamespace, 'namespaces', namespaces) + + return { nsps: (() => { 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 624eeac1..72f83dd9 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 @@ -17,7 +17,7 @@ import { * @param {boolean} auth client or not * @return {promise} resolve the confirm client */ -function initPingAction(ws, WebSocket, url, resolver, rejecter) { +function initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) { // @TODO how to we id this client can issue a CSRF // by origin? ws.onopen = function onOpenCallback() { @@ -30,7 +30,7 @@ function initPingAction(ws, WebSocket, url, resolver, rejecter) { // terminate the client ws.terminate() // return the new one with csrf header - resolver(new WebSocket(url, header)) + resolver(new WebSocket(url, Object.assign(wsOptions, header))) } catch(e) { rejecter(e) } @@ -54,14 +54,15 @@ function initWebSocketClient(WebSocket, auth = false) { /** * Create a non-protected client * @param {string} url + * @param {object} [wsOptions={}] * @return {promise} resolve to the confirmed client */ - return function createWsClient(url) { + return function createWsClient(url, wsOptions = {}) { return new Promise((resolver, rejecter) => { const _url = fixWss(url) - const unconfirmClient = new WebSocket(_url) - initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter) + const unconfirmClient = new WebSocket(_url, wsOptions) + initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) }) } } @@ -70,16 +71,17 @@ function initWebSocketClient(WebSocket, auth = false) { * Create a client with auth token * @param {string} url start with ws:// @TODO check this? * @param {string} token the jwt token + * @param {object} [wsOptions={}] extra options pass to the WebSocket object * @return {object} ws instance */ - return function createWsAuthClient(url, token) { + return function createWsAuthClient(url, token, wsOptions = {}) { const ws_url = fixWss(url) // console.log('what happen here?', url, ws_url, token) const _url = token && typeof token === 'string' ? `${ws_url}?${TOKEN_PARAM_NAME}=${token}` : ws_url return new Promise((resolver, rejecter) => { - const unconfirmClient = new WebSocket(_url) - initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter) + const unconfirmClient = new WebSocket(_url, wsOptions) + initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) }) } } diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json index f2ccfade..6baeebd0 100644 --- a/packages/ws-client-core/package.json +++ b/packages/ws-client-core/package.json @@ -55,7 +55,7 @@ }, "dependencies": { "@to1source/event": "^1.0.0", - "jsonql-constants": "^2.0.3", + "jsonql-constants": "^2.0.4", "jsonql-errors": "^1.2.1", "jsonql-params-validator": "^1.6.1", "jsonql-utils": "^1.2.0" -- Gitee From 989330d9822e4e9a4c7ec053fb7649a1429454a9 Mon Sep 17 00:00:00 2001 From: joelchu Date: Mon, 16 Mar 2020 21:42:55 +0800 Subject: [PATCH 03/66] update the createNsp to the promise interface --- .../src/core/create-nsp/create-nsp-action.js | 56 +++++++++---------- .../ws/src/core/create-nsp/create-nsp.js | 24 ++++---- .../core/create-nsp/socket-event-handler.js | 7 ++- 3 files changed, 43 insertions(+), 44 deletions(-) diff --git a/packages/@jsonql/ws/src/core/create-nsp/create-nsp-action.js b/packages/@jsonql/ws/src/core/create-nsp/create-nsp-action.js index c2f55c95..ad261ea3 100644 --- a/packages/@jsonql/ws/src/core/create-nsp/create-nsp-action.js +++ b/packages/@jsonql/ws/src/core/create-nsp/create-nsp-action.js @@ -2,10 +2,15 @@ import { createNspClient, createNspAuthClient } from '../modules' +import { + chainPromises +} from 'jsonql-utils/src/chain-promises' /** * Because the nsps can be throw away so it doesn't matter the scope * this will get reuse again + * @NOTE when we enable the standalone method this sequence will not change + * only call and reload * @param {object} opts configuration * @param {object} nspMap from contract * @param {string|null} token whether we have the token at run time @@ -16,37 +21,30 @@ const createNspAction = function(opts, nspMap, token) { let { publicNamespace, namespaces } = nspMap log(`createNspAction`, 'publicNamespace', publicNamespace, 'namespaces', namespaces) - - - return { - nsps: (() => { - // first we need to binding all the events handler - if (opts.enableAuth) { // && opts.useJwt - - return namespaces.map((namespace, i) => { - if (i === 0) { - if (token) { - opts.token = token - log('create createNspAuthClient at run time') - return { - [namespace]: createNspAuthClient(namespace, opts) - } - } - return { - [namespace]: false - } + if (opts.enableAuth) { + return chainPromises( + namespaces.map((namespace, i) => { + if (i === 0) { + if (token) { + opts.token = token + log('create createNspAuthClient at run time') + return createNspAuthClient(namespace, opts) } - return { - [namespace]: createNspClient(namespace, opts) - } - }).reduce((first, next) => Object.assign(first, next), {}) - } - // standard without login - return { - [publicNamespace]: createNspClient(false, opts) - } - })() + return Promise.resolve(false) + } + return createNspClient(namespace, opts) + }) + ) + .then(results => + results.map((result, i) => + ({ [namespaces[i]]: result })) + .reduce((a, b) => Object.assign(a, b), {}) + ) } + + return createNspClient(false, opts) + .then(nsp => ({[publicNamespace]: nsp})) } + export { createNspAction } \ No newline at end of file diff --git a/packages/@jsonql/ws/src/core/create-nsp/create-nsp.js b/packages/@jsonql/ws/src/core/create-nsp/create-nsp.js index 8f2bfe58..8174561d 100644 --- a/packages/@jsonql/ws/src/core/create-nsp/create-nsp.js +++ b/packages/@jsonql/ws/src/core/create-nsp/create-nsp.js @@ -19,20 +19,18 @@ function createNsp(opts, nspMap, ee) { const args = [opts, nspMap, ee, socketEventHandler] // now create the nsps // const { namespaces } = nspMap - const { token, log } = opts - const { nsps } = createNspAction(opts, nspMap, token) - args.push(nsps) - // log(`argument length`, args.length, args) + const { token } = opts - // binding the listeners - and it will listen to LOGOUT event - // to unbind itself, and the above call will bind it again - Reflect.apply(clientEventHandler, null, args) - // setup listener for the login event - if (opts.enableAuth) { - loginEventHandler(opts, nspMap, ee) - } - // return what input - return { opts, nspMap, ee } + return createNspAction(opts, nspMap, token) + .then(nsps => { + args.push(nsps) + Reflect.apply(clientEventHandler, null, args) + if (opts.enableAuth) { + loginEventHandler(opts, nspMap, ee) + } + // return what input + return { opts, nspMap, ee } + }) } export { createNsp } \ No newline at end of file diff --git a/packages/@jsonql/ws/src/core/create-nsp/socket-event-handler.js b/packages/@jsonql/ws/src/core/create-nsp/socket-event-handler.js index 730be690..0c58a39b 100644 --- a/packages/@jsonql/ws/src/core/create-nsp/socket-event-handler.js +++ b/packages/@jsonql/ws/src/core/create-nsp/socket-event-handler.js @@ -44,9 +44,12 @@ const errorTypeHandler = (ee, namespace, resolverName, json) => { /** * Handle the logout event when it's enableAuth * @param {object} ee eventEmitter + * @param {object} ws the WebSocket instance * @return {void} */ -const logoutEventHandler = (ee) => { +const logoutEventHandler = (ee, ws) => { + // @TODO need to issue the logout callback here + // listen to the LOGOUT_EVENT_NAME when this is a private nsp ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() { try { @@ -158,6 +161,6 @@ export function socketEventHandler(namespace, ws, ee, isPrivate, opts) { } if (isPrivate) { - logoutEventHandler(ee) + logoutEventHandler(ee, ws) } } -- Gitee From 1fad5d5926053abe0d3b1d92c12dac8ec80fcf72 Mon Sep 17 00:00:00 2001 From: joelchu Date: Mon, 16 Mar 2020 22:06:14 +0800 Subject: [PATCH 04/66] rename to intercom-methods we are going couple more there --- packages/ws-client-core/index.js | 2 +- .../src/share/{init-ping-methods.js => intercom-methods.js} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/ws-client-core/src/share/{init-ping-methods.js => intercom-methods.js} (100%) diff --git a/packages/ws-client-core/index.js b/packages/ws-client-core/index.js index 0debf854..b7988695 100644 --- a/packages/ws-client-core/index.js +++ b/packages/ws-client-core/index.js @@ -44,7 +44,7 @@ import { import { createInitPing, extractPingResult -} from './src/share/init-ping-methods' +} from './src/share/intercom-methods' // export export { diff --git a/packages/ws-client-core/src/share/init-ping-methods.js b/packages/ws-client-core/src/share/intercom-methods.js similarity index 100% rename from packages/ws-client-core/src/share/init-ping-methods.js rename to packages/ws-client-core/src/share/intercom-methods.js -- Gitee From 5bda954c9b04074988070a9ce85424eefa28d7fe Mon Sep 17 00:00:00 2001 From: joelchu Date: Mon, 16 Mar 2020 22:28:27 +0800 Subject: [PATCH 05/66] rename the socketEventHandler to bindSocketEventHandler to match both and less confusion which is which --- ...andler.js => bind-socket-event-handler.js} | 2 +- .../ws/src/core/create-nsp/create-nsp.js | 4 ++-- packages/ws-client-core/index.js | 11 +++++----- .../src/share/client-event-handler.js | 4 ++-- .../src/share/intercom-methods.js | 20 ++++++++++++++++++- packages/ws-client-core/tests/init.test.js | 2 +- 6 files changed, 30 insertions(+), 13 deletions(-) rename packages/@jsonql/ws/src/core/create-nsp/{socket-event-handler.js => bind-socket-event-handler.js} (98%) diff --git a/packages/@jsonql/ws/src/core/create-nsp/socket-event-handler.js b/packages/@jsonql/ws/src/core/create-nsp/bind-socket-event-handler.js similarity index 98% rename from packages/@jsonql/ws/src/core/create-nsp/socket-event-handler.js rename to packages/@jsonql/ws/src/core/create-nsp/bind-socket-event-handler.js index 0c58a39b..5de5aecb 100644 --- a/packages/@jsonql/ws/src/core/create-nsp/socket-event-handler.js +++ b/packages/@jsonql/ws/src/core/create-nsp/bind-socket-event-handler.js @@ -70,7 +70,7 @@ const logoutEventHandler = (ee, ws) => { * @param {object} opts configuration * @return {object} promise resolve after the onopen event */ -export function socketEventHandler(namespace, ws, ee, isPrivate, opts) { +export function bindSocketEventHandler(namespace, ws, ee, isPrivate, opts) { const { log } = opts log(`log test, isPrivate:`, isPrivate) diff --git a/packages/@jsonql/ws/src/core/create-nsp/create-nsp.js b/packages/@jsonql/ws/src/core/create-nsp/create-nsp.js index 8174561d..4992b7cd 100644 --- a/packages/@jsonql/ws/src/core/create-nsp/create-nsp.js +++ b/packages/@jsonql/ws/src/core/create-nsp/create-nsp.js @@ -5,7 +5,7 @@ import { clientEventHandler } from '../modules' // local import { createNspAction } from './create-nsp-action' import { loginEventHandler } from './login-event-handler' -import { socketEventHandler } from './socket-event-handler' +import { bindSocketEventHandler } from './bind-socket-event-handler' /** * create the NSP(s) and determine if this require auth or not @@ -16,7 +16,7 @@ import { socketEventHandler } from './socket-event-handler' */ function createNsp(opts, nspMap, ee) { // arguments for clientEventHandler - const args = [opts, nspMap, ee, socketEventHandler] + const args = [opts, nspMap, ee, bindSocketEventHandler] // now create the nsps // const { namespaces } = nspMap const { token } = opts diff --git a/packages/ws-client-core/index.js b/packages/ws-client-core/index.js index b7988695..37c2526e 100644 --- a/packages/ws-client-core/index.js +++ b/packages/ws-client-core/index.js @@ -1,10 +1,8 @@ // This is the module entry point - import { wsClientCore, wsClientCoreAction } from './src/api' - import { wsCoreCheckMap, wsCoreConstProps, @@ -17,8 +15,7 @@ import { createNspClient, createNspAuthClient } from './src/share/create-nsp-clients' - - +// error handler import { triggerNamespacesOnError, handleNamespaceOnError @@ -43,7 +40,8 @@ import { // new ping methods import { createInitPing, - extractPingResult + extractPingResult, + createIntercomPayload } from './src/share/intercom-methods' // export @@ -74,5 +72,6 @@ export { createCombineClient, createInitPing, - extractPingResult + extractPingResult, + createIntercomPayload } diff --git a/packages/ws-client-core/src/share/client-event-handler.js b/packages/ws-client-core/src/share/client-event-handler.js index 7f1251f7..a9b94300 100644 --- a/packages/ws-client-core/src/share/client-event-handler.js +++ b/packages/ws-client-core/src/share/client-event-handler.js @@ -129,7 +129,7 @@ const disconnectHandler = (nsps, namespaces, ee, opts) => { * @param {object} opts configuration * @param {object} nspMap this is not in the opts * @param {object} ee Event Emitter instance - * @param {function} bindWsHandler binding the ee to ws --> this is the core bit + * @param {function} bindSocketEventHandler binding the ee to ws --> this is the core bit * @param {object} nsps namespaced nsp * @return {void} nothing */ @@ -156,7 +156,7 @@ export function clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsp log('[call bindWsHandler]', isPrivate, namespace) let args = [namespace, nsps[namespace], ee, isPrivate, opts] - + // @TODO need to double check this if (opts.serverType === SOCKET_IO) { let { nspGroup } = nspMap args.push(nspGroup[namespace]) diff --git a/packages/ws-client-core/src/share/intercom-methods.js b/packages/ws-client-core/src/share/intercom-methods.js index f2c433da..58258430 100644 --- a/packages/ws-client-core/src/share/intercom-methods.js +++ b/packages/ws-client-core/src/share/intercom-methods.js @@ -48,4 +48,22 @@ function extractPingResult(payload) { } -export { createInitPing, extractPingResult } \ No newline at end of file +/** + * Create a generic intercom method + * @param {string} type the event type + * @param {array} args if any + * @return {string} formatted payload to send + */ +function createIntercomPayload(type, ...args) { + const ts = timestamp() + let payload = [type].concat(args) + payload.push(ts) + return createQueryStr(INTERCOM_RESOLVER_NAME, payload) +} + + +export { + createInitPing, + extractPingResult, + createIntercomPayload +} \ No newline at end of file diff --git a/packages/ws-client-core/tests/init.test.js b/packages/ws-client-core/tests/init.test.js index 35e66121..b3117235 100644 --- a/packages/ws-client-core/tests/init.test.js +++ b/packages/ws-client-core/tests/init.test.js @@ -8,7 +8,7 @@ const { const debug = require('debug')('jsonql-ws-server:test:ws') const port = 8899 -const { createInitPing, extractPingResult } = require('../src/share/init-ping-methods') +const { createInitPing, extractPingResult } = require('../src/share/intercom-methods') test.before(async t => { const { app } = await wsServer() -- Gitee From e4e587c004d5fb02f468a9621d9512431437a522 Mon Sep 17 00:00:00 2001 From: joelchu Date: Mon, 16 Mar 2020 22:32:40 +0800 Subject: [PATCH 06/66] test:basic passed and can see the csrf token in the transmit log --- packages/@jsonql/ws/main.js | 2674 ++++++++++++++++++++++++++++--- packages/@jsonql/ws/main.js.map | 2 +- 2 files changed, 2451 insertions(+), 225 deletions(-) diff --git a/packages/@jsonql/ws/main.js b/packages/@jsonql/ws/main.js index 03327f58..0972f5dd 100644 --- a/packages/@jsonql/ws/main.js +++ b/packages/@jsonql/ws/main.js @@ -697,6 +697,7 @@ var checkIsAny = function(value, checkNull) { // the core stuff to id if it's calling with jsonql var DATA_KEY = 'data'; var ERROR_KEY = 'error'; +var HEADERS_KEY = 'headers'; var JSONQL_PATH = 'jsonql'; @@ -710,6 +711,8 @@ var DEFAULT_TYPE = 'any'; var QUERY_NAME = 'query'; var MUTATION_NAME = 'mutation'; var SOCKET_NAME = 'socket'; +var QUERY_ARG_NAME = 'args'; +var TIMESTAMP_PARAM_NAME = 'TS'; // for contract-cli var KEY_WORD = 'continue'; var PUBLIC_KEY = 'public'; @@ -718,6 +721,8 @@ var LOGIN_FN_NAME = 'login'; var LOGOUT_FN_NAME = 'logout'; 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 @@ -748,9 +753,24 @@ var WS_OPT_PROP_KEY = 'wsOptions'; var CONTRACT_PROP_KEY = 'contract'; var TOKEN_PROP_KEY = 'token'; + + /* socket.js */ + +// the constants file is gettig too large +// we need to split up and group the related constant in one file +// also it makes the other module easiler to id what they are importing +// use throughout the clients +var SOCKET_PING_EVENT_NAME = '__ping__'; // when init connection do a ping var LOGIN_EVENT_NAME = '__login__'; var LOGOUT_EVENT_NAME = '__logout__'; var DISCONNECT_EVENT_NAME = '__disconnect__'; +// instead of using an event name in place of resolverName in the param +// we use this internal resolverName instead, and in type using the event names +var INTERCOM_RESOLVER_NAME = '__intercom__'; +// for ws servers +var WS_REPLY_TYPE = '__reply__'; +var WS_EVT_NAME = '__event__'; +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'; @@ -6599,6 +6619,25 @@ var inArray$1 = function (arr, value) { return !!arr.filter(function (a) { retur // quick and dirty to turn non array to array var toArray$1 = function (arg) { return isArray(arg) ? arg : [arg]; }; +/** + * parse string to json or just return the original value if error happened + * @param {*} n input + * @param {boolean} [t=true] or throw + * @return {*} json object on success + */ +var parseJson = function(n, t) { + if ( t === void 0 ) t=true; + + try { + return JSON.parse(n) + } catch(e) { + if (t) { + return n + } + throw new Error(e) + } +}; + /** * @param {object} obj for search * @param {string} key target @@ -6626,6 +6665,18 @@ var createEvt = function () { return args.join('_'); }; +/** + * small util to make sure the return value is valid JSON object + * @param {*} n input + * @return {object} correct JSON object + */ +var toJson = function (n) { + if (typeof n === 'string') { + return parseJson(n) + } + return parseJson(JSON.stringify(n)) +}; + /** * Simple check if the prop is function * @param {*} prop input @@ -6766,6 +6817,74 @@ function extractSocketPart(contract) { return false } +/** + * @param {boolean} sec return in second or not + * @return {number} timestamp + */ +var timestamp = function (sec) { + if ( sec === void 0 ) sec = false; + + var time = Date.now(); + return sec ? Math.floor( time / 1000 ) : time +}; + +// ported from jsonql-params-validator + +/** + * @param {*} args arguments to send + *@return {object} formatted payload + */ +var formatPayload = function (args) { + var obj; + + return ( + ( obj = {}, obj[QUERY_ARG_NAME] = args, obj ) +); +}; + +/** + * wrapper method to add the timestamp as well + * @param {string} resolverName + * @param {*} payload + * @return {object} delierable + */ +function createDeliverable(resolverName, payload) { + var obj; + + return ( obj = {}, obj[resolverName] = payload, obj[TIMESTAMP_PARAM_NAME] = [ timestamp() ], obj ) +} + +/** + * @param {string} resolverName name of function + * @param {array} [args=[]] from the ...args + * @param {boolean} [jsonp = false] add v1.3.0 to koa + * @return {object} formatted argument + */ +function createQuery(resolverName, args, jsonp) { + if ( args === void 0 ) args = []; + if ( jsonp === void 0 ) jsonp = false; + + if (isString(resolverName) && isArray(args)) { + var payload = formatPayload(args); + if (jsonp === true) { + return payload + } + return createDeliverable(resolverName, payload) + } + throw new JsonqlValidationError("[createQuery] expect resolverName to be string and args to be array!", { resolverName: resolverName, args: args }) +} + +/** + * string version of the createQuery + * @return {string} + */ +function createQueryStr(resolverName, args, jsonp) { + if ( args === void 0 ) args = []; + if ( jsonp === void 0 ) jsonp = false; + + return JSON.stringify(createQuery(resolverName, args, jsonp)) +} + // take out all the namespace related methods in one place for easy to find var SOCKET_NOT_FOUND_ERR = "socket not found in contract!"; var SIZE = 'size'; @@ -6862,6 +6981,57 @@ function getNspInfoByConfig(config) { return Object.assign(nspInfo, { namespaces: namespaces }) } +// There are the socket related methods ported back from + +var PAYLOAD_NOT_DECODED_ERR = 'payload can not decoded'; +var WS_KEYS = [ + WS_REPLY_TYPE, + WS_EVT_NAME, + WS_DATA_NAME +]; + +/** + * @param {string|object} payload should be string when reply but could be transformed + * @return {boolean} true is OK + */ +var isWsReply = function (payload) { + var json = isString(payload) ? toJson(payload) : payload; + var data = json.data; + if (data) { + var result = WS_KEYS.filter(function (key) { return isObjectHasKey$1(data, key); }); + return (result.length === WS_KEYS.length) ? data : false + } + return false +}; + +/** + * @param {string|object} data received data + * @param {function} [cb=nil] this is for extracting the TS field or when it's error + * @return {object} false on failed + */ +var extractWsPayload = function (payload, cb) { + if ( cb === void 0 ) cb = nil; + + try { + var json = toJson(payload); + // now handle the data + var _data; + if ((_data = isWsReply(json)) !== false) { + // note the ts property is on its own + cb(TIMESTAMP_PARAM_NAME, json[TIMESTAMP_PARAM_NAME]); + + return { + data: toJson(_data[WS_DATA_NAME]), + resolverName: _data[WS_EVT_NAME], + type: _data[WS_REPLY_TYPE] + } + } + throw new JsonqlError$1(PAYLOAD_NOT_DECODED_ERR, payload) + } catch(e) { + return cb(ERROR_KEY, e) + } +}; + // group all the small functions here @@ -7754,7 +7924,7 @@ var disconnectHandler = function (nsps, namespaces, ee, opts) { * @param {object} opts configuration * @param {object} nspMap this is not in the opts * @param {object} ee Event Emitter instance - * @param {function} bindWsHandler binding the ee to ws --> this is the core bit + * @param {function} bindSocketEventHandler binding the ee to ws --> this is the core bit * @param {object} nsps namespaced nsp * @return {void} nothing */ @@ -7781,7 +7951,7 @@ function clientEventHandler$1(opts, nspMap, ee, bindSocketEventHandler, nsps) { log('[call bindWsHandler]', isPrivate, namespace); var args = [namespace, nsps[namespace], ee, isPrivate, opts]; - + // @TODO need to double check this if (opts.serverType === SOCKET_IO) { var nspGroup = nspMap.nspGroup; args.push(nspGroup[namespace]); @@ -7804,16 +7974,44 @@ function clientEventHandler$1(opts, nspMap, ee, bindSocketEventHandler, nsps) { disconnectHandler(nsps, namespaces, ee, opts); } +// this will be part of the init client sequence +var CSRF_HEADER_NOT_EXIST_ERR = 'CSRF header is not in the received payload'; + +/** + * call the server to get a csrf token + * @return {string} formatted payload to send to the server + */ +function createInitPing() { + var ts = timestamp(); + return createQueryStr(INTERCOM_RESOLVER_NAME, [SOCKET_PING_EVENT_NAME, ts]) +} + +/** + * Take the raw on.message result back then decoded it + * @param {*} payload the raw result from server + * @return {object} the csrf payload + */ +function extractPingResult(payload) { + var obj; + + var json = toJson(payload); + var result = extractWsPayload(json); + if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) { + return ( obj = {}, obj[HEADERS_KEY] = result[DATA_KEY], obj ) + } + throw new JsonqlError$1('extractPingResult', CSRF_HEADER_NOT_EXIST_ERR) +} + /* base.js */ var ERROR_KEY$1 = 'error'; -var QUERY_ARG_NAME = 'args'; -var TIMESTAMP_PARAM_NAME = 'TS'; +var QUERY_ARG_NAME$1 = 'args'; +var TIMESTAMP_PARAM_NAME$1 = 'TS'; var LOGIN_EVENT_NAME$1 = '__login__'; var LOGOUT_EVENT_NAME$1 = '__logout__'; // for ws servers -var WS_REPLY_TYPE = '__reply__'; -var WS_EVT_NAME = '__event__'; -var WS_DATA_NAME = '__data__'; +var WS_REPLY_TYPE$1 = '__reply__'; +var WS_EVT_NAME$1 = '__event__'; +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'; @@ -7828,6 +8026,9 @@ var ACKNOWLEDGE_REPLY_TYPE = 'acknowledge_reply'; var JS_WS_NAME = 'ws'; var TOKEN_PARAM_NAME = 'token'; +var NSP_AUTH_CLIENT = 'nspAuthClient'; +var NSP_CLIENT = 'nspClient'; + // jsonql-ws-core takes over the check configuration // constant props var wsClientConstProps = { @@ -7837,18 +8038,67 @@ var wsClientConstProps = { // pass the different type of ws to generate the client +/** + * Group the ping and get respond create new client in one + * @param {object} ws + * @param {object} WebSocket + * @param {string} url + * @param {function} resolver + * @param {function} rejecter + * @param {boolean} auth client or not + * @return {promise} resolve the confirm client + */ +function initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) { + // @TODO how to we id this client can issue a CSRF + // by origin? + ws.onopen = function onOpenCallback() { + ws.send(createInitPing()); + }; + + ws.onmessage = function onMessageCallback(payload) { + try { + var header = extractPingResult(payload.data); + // terminate the client + ws.terminate(); + // return the new one with csrf header + resolver(new WebSocket(url, Object.assign(wsOptions, header))); + } catch(e) { + rejecter(e); + } + }; + + ws.onerror = function onErrorCallback(err) { + rejecter(err); + }; +} + /** * The bug was in the wsOptions where ws don't need it but socket.io do * 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 */ function initWebSocketClient(WebSocket, auth) { if ( auth === void 0 ) auth = false; if (auth === false) { - return function createWsClient(url) { - return new WebSocket(fixWss(url)) + /** + * Create a non-protected client + * @param {string} url + * @param {object} [wsOptions={}] + * @return {promise} resolve to the confirmed client + */ + return function createWsClient(url, wsOptions) { + if ( wsOptions === void 0 ) wsOptions = {}; + + + return new Promise(function (resolver, rejecter) { + var _url = fixWss(url); + var unconfirmClient = new WebSocket(_url, wsOptions); + initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions); + }) } } @@ -7856,241 +8106,2221 @@ function initWebSocketClient(WebSocket, auth) { * Create a client with auth token * @param {string} url start with ws:// @TODO check this? * @param {string} token the jwt token + * @param {object} [wsOptions={}] extra options pass to the WebSocket object * @return {object} ws instance */ - return function createWsAuthClient(url, token) { + return function createWsAuthClient(url, token, wsOptions) { + if ( wsOptions === void 0 ) wsOptions = {}; + var ws_url = fixWss(url); // console.log('what happen here?', url, ws_url, token) - var uri = token && typeof token === 'string' ? (ws_url + "?" + TOKEN_PARAM_NAME + "=" + token) : ws_url; - try { - return new WebSocket(uri) - } catch(e) { - console.error('WebSocket Connection Error', e); - return false - } + var _url = token && typeof token === 'string' ? (ws_url + "?" + TOKEN_PARAM_NAME + "=" + token) : ws_url; + + return new Promise(function (resolver, rejecter) { + var unconfirmClient = new WebSocket(_url, wsOptions); + initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions); + }) } } -/** - * Because the nsps can be throw away so it doesn't matter the scope - * this will get reuse again - * @param {object} opts configuration - * @param {object} nspMap from contract - * @param {string|null} token whether we have the token at run time - * @return {object} nsps namespace with namespace as key - */ -var createNspAction$1 = function(opts, nspMap, token) { - var log = opts.log; - var publicNamespace = nspMap.publicNamespace; - var namespaces = nspMap.namespaces; - log("createNspAction", 'publicNamespace', publicNamespace, 'namespaces', namespaces); +/** Detect free variable `global` from Node.js. */ +var freeGlobal$1 = typeof global$1 == 'object' && global$1 && global$1.Object === Object && global$1; - return { - nsps: (function () { - var obj; +/** Detect free variable `self`. */ +var freeSelf$1 = typeof self == 'object' && self && self.Object === Object && self; - // first we need to binding all the events handler - if (opts.enableAuth) { // && opts.useJwt - - return namespaces.map(function (namespace, i) { - var obj, obj$1, obj$2; - - if (i === 0) { - if (token) { - opts.token = token; - log('create createNspAuthClient at run time'); - return ( obj = {}, obj[namespace] = createNspAuthClient(namespace, opts), obj ) - } - return ( obj$1 = {}, obj$1[namespace] = false, obj$1 ) - } - return ( obj$2 = {}, obj$2[namespace] = createNspClient(namespace, opts), obj$2 ) - }).reduce(function (first, next) { return Object.assign(first, next); }, {}) - } - // standard without login - return ( obj = {}, obj[publicNamespace] = createNspClient(false, opts), obj ) - })() - } -}; +/** Used as a reference to the global object. */ +var root$1 = freeGlobal$1 || freeSelf$1 || Function('return this')(); -// @BUG when call disconnected +/** Built-in value references. */ +var Symbol$1 = root$1.Symbol; + +/** Used for built-in method references. */ +var objectProto$f = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$c = objectProto$f.hasOwnProperty; /** - * create a login event handler - * @param {object} opts configurations - * @param {object} nspMap contain all the required info - * @param {object} ee event emitter - * @return {void} + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. */ -function loginEventHandler(opts, nspMap, ee) { - var log = opts.log; - var namespaces = nspMap.namespaces; +var nativeObjectToString$2 = objectProto$f.toString; - ee.$only(LOGIN_EVENT_NAME$1, function loginEventHandlerCallback(tokenFromLoginAction) { - - log('createClient LOGIN_EVENT_NAME $only handler'); +/** Built-in value references. */ +var symToStringTag$2 = Symbol$1 ? Symbol$1.toStringTag : undefined; - clearMainEmitEvt(ee, namespaces); - // console.log('LOGIN_EVENT_NAME', token) - var newNsps = createNspAction(opts, nspMap, tokenFromLoginAction); - // rebind it - Reflect.apply( - clientEventHandler, // @NOTE is this the problem that cause the hang up? - null, - args.concat([newNsps.namespaces, newNsps.nsps]) - ); - }); +/** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ +function getRawTag$1(value) { + var isOwn = hasOwnProperty$c.call(value, symToStringTag$2), + tag = value[symToStringTag$2]; + + try { + value[symToStringTag$2] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString$2.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag$2] = tag; + } else { + delete value[symToStringTag$2]; + } + } + return result; } +/** Used for built-in method references. */ +var objectProto$g = Object.prototype; + /** - * Checks if `value` is classified as an `Array` object. + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString$3 = objectProto$g.toString; + +/** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ +function objectToString$1(value) { + return nativeObjectToString$3.call(value); +} + +/** `Object#toString` result references. */ +var nullTag$1 = '[object Null]', + undefinedTag$1 = '[object Undefined]'; + +/** Built-in value references. */ +var symToStringTag$3 = Symbol$1 ? Symbol$1.toStringTag : undefined; + +/** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +function baseGetTag$1(value) { + if (value == null) { + return value === undefined ? undefinedTag$1 : nullTag$1; + } + return (symToStringTag$3 && symToStringTag$3 in Object(value)) + ? getRawTag$1(value) + : objectToString$1(value); +} + +/** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ +function overArg$1(func, transform) { + return function(arg) { + return func(transform(arg)); + }; +} + +/** Built-in value references. */ +var getPrototype$1 = overArg$1(Object.getPrototypeOf, Object); + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". * * @static * @memberOf _ - * @since 0.1.0 + * @since 4.0.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. * @example * - * _.isArray([1, 2, 3]); + * _.isObjectLike({}); * // => true * - * _.isArray(document.body.children); + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); * // => false * - * _.isArray('abc'); + * _.isObjectLike(null); * // => false + */ +function isObjectLike$1(value) { + return value != null && typeof value == 'object'; +} + +/** `Object#toString` result references. */ +var objectTag$4 = '[object Object]'; + +/** Used for built-in method references. */ +var funcProto$3 = Function.prototype, + objectProto$h = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString$3 = funcProto$3.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty$d = objectProto$h.hasOwnProperty; + +/** Used to infer the `Object` constructor. */ +var objectCtorString$1 = funcToString$3.call(Object); + +/** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. * - * _.isArray(_.noop); + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true */ -var isArray$1 = Array.isArray; +function isPlainObject$1(value) { + if (!isObjectLike$1(value) || baseGetTag$1(value) != objectTag$4) { + return false; + } + var proto = getPrototype$1(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty$d.call(proto, 'constructor') && proto.constructor; + return typeof Ctor == 'function' && Ctor instanceof Ctor && + funcToString$3.call(Ctor) == objectCtorString$1; +} -/** Detect free variable `global` from Node.js. */ -var freeGlobal$1 = typeof global$1 == 'object' && global$1 && global$1.Object === Object && global$1; +/** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ +function listCacheClear$1() { + this.__data__ = []; + this.size = 0; +} -/** Detect free variable `self`. */ -var freeSelf$1 = typeof self == 'object' && self && self.Object === Object && self; +/** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ +function eq$1(value, other) { + return value === other || (value !== value && other !== other); +} -/** Used as a reference to the global object. */ -var root$1 = freeGlobal$1 || freeSelf$1 || Function('return this')(); +/** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function assocIndexOf$1(array, key) { + var length = array.length; + while (length--) { + if (eq$1(array[length][0], key)) { + return length; + } + } + return -1; +} + +/** Used for built-in method references. */ +var arrayProto$1 = Array.prototype; /** Built-in value references. */ -var Symbol$1 = root$1.Symbol; +var splice$1 = arrayProto$1.splice; -/** Used for built-in method references. */ -var objectProto$f = Object.prototype; +/** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function listCacheDelete$1(key) { + var data = this.__data__, + index = assocIndexOf$1(data, key); -/** Used to check objects for own properties. */ -var hasOwnProperty$c = objectProto$f.hasOwnProperty; + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice$1.call(data, index, 1); + } + --this.size; + return true; +} /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. */ -var nativeObjectToString$2 = objectProto$f.toString; +function listCacheGet$1(key) { + var data = this.__data__, + index = assocIndexOf$1(data, key); + + return index < 0 ? undefined : data[index][1]; +} + +/** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function listCacheHas$1(key) { + return assocIndexOf$1(this.__data__, key) > -1; +} + +/** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ +function listCacheSet$1(key, value) { + var data = this.__data__, + index = assocIndexOf$1(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; +} + +/** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function ListCache$1(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `ListCache`. +ListCache$1.prototype.clear = listCacheClear$1; +ListCache$1.prototype['delete'] = listCacheDelete$1; +ListCache$1.prototype.get = listCacheGet$1; +ListCache$1.prototype.has = listCacheHas$1; +ListCache$1.prototype.set = listCacheSet$1; + +/** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ +function stackClear$1() { + this.__data__ = new ListCache$1; + this.size = 0; +} + +/** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function stackDelete$1(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; +} + +/** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function stackGet$1(key) { + return this.__data__.get(key); +} + +/** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function stackHas$1(key) { + return this.__data__.has(key); +} + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject$1(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); +} + +/** `Object#toString` result references. */ +var asyncTag$1 = '[object AsyncFunction]', + funcTag$2 = '[object Function]', + genTag$1 = '[object GeneratorFunction]', + proxyTag$1 = '[object Proxy]'; + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction$1(value) { + if (!isObject$1(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag$1(value); + return tag == funcTag$2 || tag == genTag$1 || tag == asyncTag$1 || tag == proxyTag$1; +} + +/** Used to detect overreaching core-js shims. */ +var coreJsData$1 = root$1['__core-js_shared__']; + +/** Used to detect methods masquerading as native. */ +var maskSrcKey$1 = (function() { + var uid = /[^.]+$/.exec(coreJsData$1 && coreJsData$1.keys && coreJsData$1.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; +}()); + +/** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ +function isMasked$1(func) { + return !!maskSrcKey$1 && (maskSrcKey$1 in func); +} + +/** Used for built-in method references. */ +var funcProto$4 = Function.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString$4 = funcProto$4.toString; + +/** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ +function toSource$1(func) { + if (func != null) { + try { + return funcToString$4.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; +} + +/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ +var reRegExpChar$1 = /[\\^$.*+?()[\]{}|]/g; + +/** Used to detect host constructors (Safari). */ +var reIsHostCtor$1 = /^\[object .+?Constructor\]$/; + +/** Used for built-in method references. */ +var funcProto$5 = Function.prototype, + objectProto$i = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString$5 = funcProto$5.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty$e = objectProto$i.hasOwnProperty; + +/** Used to detect if a method is native. */ +var reIsNative$1 = RegExp('^' + + funcToString$5.call(hasOwnProperty$e).replace(reRegExpChar$1, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ +function baseIsNative$1(value) { + if (!isObject$1(value) || isMasked$1(value)) { + return false; + } + var pattern = isFunction$1(value) ? reIsNative$1 : reIsHostCtor$1; + return pattern.test(toSource$1(value)); +} + +/** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ +function getValue$1(object, key) { + return object == null ? undefined : object[key]; +} + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative$1(object, key) { + var value = getValue$1(object, key); + return baseIsNative$1(value) ? value : undefined; +} + +/* Built-in method references that are verified to be native. */ +var Map$2 = getNative$1(root$1, 'Map'); + +/* Built-in method references that are verified to be native. */ +var nativeCreate$1 = getNative$1(Object, 'create'); + +/** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ +function hashClear$1() { + this.__data__ = nativeCreate$1 ? nativeCreate$1(null) : {}; + this.size = 0; +} + +/** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function hashDelete$1(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; +} + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED$3 = '__lodash_hash_undefined__'; + +/** Used for built-in method references. */ +var objectProto$j = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$f = objectProto$j.hasOwnProperty; + +/** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function hashGet$1(key) { + var data = this.__data__; + if (nativeCreate$1) { + var result = data[key]; + return result === HASH_UNDEFINED$3 ? undefined : result; + } + return hasOwnProperty$f.call(data, key) ? data[key] : undefined; +} + +/** Used for built-in method references. */ +var objectProto$k = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$g = objectProto$k.hasOwnProperty; + +/** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function hashHas$1(key) { + var data = this.__data__; + return nativeCreate$1 ? (data[key] !== undefined) : hasOwnProperty$g.call(data, key); +} + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED$4 = '__lodash_hash_undefined__'; + +/** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ +function hashSet$1(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate$1 && value === undefined) ? HASH_UNDEFINED$4 : value; + return this; +} + +/** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Hash$1(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `Hash`. +Hash$1.prototype.clear = hashClear$1; +Hash$1.prototype['delete'] = hashDelete$1; +Hash$1.prototype.get = hashGet$1; +Hash$1.prototype.has = hashHas$1; +Hash$1.prototype.set = hashSet$1; + +/** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ +function mapCacheClear$1() { + this.size = 0; + this.__data__ = { + 'hash': new Hash$1, + 'map': new (Map$2 || ListCache$1), + 'string': new Hash$1 + }; +} + +/** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ +function isKeyable$1(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); +} + +/** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ +function getMapData$1(map, key) { + var data = map.__data__; + return isKeyable$1(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; +} + +/** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function mapCacheDelete$1(key) { + var result = getMapData$1(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; +} + +/** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function mapCacheGet$1(key) { + return getMapData$1(this, key).get(key); +} + +/** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function mapCacheHas$1(key) { + return getMapData$1(this, key).has(key); +} + +/** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ +function mapCacheSet$1(key, value) { + var data = getMapData$1(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; +} + +/** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function MapCache$1(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `MapCache`. +MapCache$1.prototype.clear = mapCacheClear$1; +MapCache$1.prototype['delete'] = mapCacheDelete$1; +MapCache$1.prototype.get = mapCacheGet$1; +MapCache$1.prototype.has = mapCacheHas$1; +MapCache$1.prototype.set = mapCacheSet$1; + +/** Used as the size to enable large array optimizations. */ +var LARGE_ARRAY_SIZE$1 = 200; + +/** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ +function stackSet$1(key, value) { + var data = this.__data__; + if (data instanceof ListCache$1) { + var pairs = data.__data__; + if (!Map$2 || (pairs.length < LARGE_ARRAY_SIZE$1 - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache$1(pairs); + } + data.set(key, value); + this.size = data.size; + return this; +} + +/** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Stack$1(entries) { + var data = this.__data__ = new ListCache$1(entries); + this.size = data.size; +} + +// Add methods to `Stack`. +Stack$1.prototype.clear = stackClear$1; +Stack$1.prototype['delete'] = stackDelete$1; +Stack$1.prototype.get = stackGet$1; +Stack$1.prototype.has = stackHas$1; +Stack$1.prototype.set = stackSet$1; + +var defineProperty$1 = (function() { + try { + var func = getNative$1(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} +}()); + +/** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function baseAssignValue$1(object, key, value) { + if (key == '__proto__' && defineProperty$1) { + defineProperty$1(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } +} + +/** + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function assignMergeValue$1(object, key, value) { + if ((value !== undefined && !eq$1(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue$1(object, key, value); + } +} + +/** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ +function createBaseFor$1(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; +} + +/** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ +var baseFor$1 = createBaseFor$1(); + +/** Detect free variable `exports`. */ +var freeExports$3 = typeof exports == 'object' && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule$3 = freeExports$3 && typeof module == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports$3 = freeModule$3 && freeModule$3.exports === freeExports$3; + +/** Built-in value references. */ +var Buffer$2 = moduleExports$3 ? root$1.Buffer : undefined, + allocUnsafe$1 = Buffer$2 ? Buffer$2.allocUnsafe : undefined; + +/** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ +function cloneBuffer$1(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe$1 ? allocUnsafe$1(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; +} + +/** Built-in value references. */ +var Uint8Array$1 = root$1.Uint8Array; + +/** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ +function cloneArrayBuffer$1(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array$1(result).set(new Uint8Array$1(arrayBuffer)); + return result; +} + +/** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ +function cloneTypedArray$1(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer$1(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); +} + +/** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ +function copyArray$1(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; +} + +/** Built-in value references. */ +var objectCreate$1 = Object.create; + +/** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ +var baseCreate$1 = (function() { + function object() {} + return function(proto) { + if (!isObject$1(proto)) { + return {}; + } + if (objectCreate$1) { + return objectCreate$1(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; +}()); + +/** Used for built-in method references. */ +var objectProto$l = Object.prototype; + +/** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ +function isPrototype$1(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto$l; + + return value === proto; +} + +/** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ +function initCloneObject$1(object) { + return (typeof object.constructor == 'function' && !isPrototype$1(object)) + ? baseCreate$1(getPrototype$1(object)) + : {}; +} + +/** `Object#toString` result references. */ +var argsTag$3 = '[object Arguments]'; + +/** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ +function baseIsArguments$1(value) { + return isObjectLike$1(value) && baseGetTag$1(value) == argsTag$3; +} + +/** Used for built-in method references. */ +var objectProto$m = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$h = objectProto$m.hasOwnProperty; + +/** Built-in value references. */ +var propertyIsEnumerable$2 = objectProto$m.propertyIsEnumerable; + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +var isArguments$1 = baseIsArguments$1(function() { return arguments; }()) ? baseIsArguments$1 : function(value) { + return isObjectLike$1(value) && hasOwnProperty$h.call(value, 'callee') && + !propertyIsEnumerable$2.call(value, 'callee'); +}; + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray$1 = Array.isArray; + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER$2 = 9007199254740991; + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength$1(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER$2; +} + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike$2(value) { + return value != null && isLength$1(value.length) && !isFunction$1(value); +} + +/** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ +function isArrayLikeObject$1(value) { + return isObjectLike$1(value) && isArrayLike$2(value); +} + +/** + * This method returns `false`. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `false`. + * @example + * + * _.times(2, _.stubFalse); + * // => [false, false] + */ +function stubFalse$1() { + return false; +} + +/** Detect free variable `exports`. */ +var freeExports$4 = typeof exports == 'object' && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule$4 = freeExports$4 && typeof module == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports$4 = freeModule$4 && freeModule$4.exports === freeExports$4; + +/** Built-in value references. */ +var Buffer$3 = moduleExports$4 ? root$1.Buffer : undefined; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeIsBuffer$1 = Buffer$3 ? Buffer$3.isBuffer : undefined; + +/** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ +var isBuffer$1 = nativeIsBuffer$1 || stubFalse$1; + +/** `Object#toString` result references. */ +var argsTag$4 = '[object Arguments]', + arrayTag$2 = '[object Array]', + boolTag$2 = '[object Boolean]', + dateTag$2 = '[object Date]', + errorTag$2 = '[object Error]', + funcTag$3 = '[object Function]', + mapTag$3 = '[object Map]', + numberTag$3 = '[object Number]', + objectTag$5 = '[object Object]', + regexpTag$2 = '[object RegExp]', + setTag$3 = '[object Set]', + stringTag$3 = '[object String]', + weakMapTag$2 = '[object WeakMap]'; + +var arrayBufferTag$2 = '[object ArrayBuffer]', + dataViewTag$3 = '[object DataView]', + float32Tag$1 = '[object Float32Array]', + float64Tag$1 = '[object Float64Array]', + int8Tag$1 = '[object Int8Array]', + int16Tag$1 = '[object Int16Array]', + int32Tag$1 = '[object Int32Array]', + uint8Tag$1 = '[object Uint8Array]', + uint8ClampedTag$1 = '[object Uint8ClampedArray]', + uint16Tag$1 = '[object Uint16Array]', + uint32Tag$1 = '[object Uint32Array]'; + +/** Used to identify `toStringTag` values of typed arrays. */ +var typedArrayTags$1 = {}; +typedArrayTags$1[float32Tag$1] = typedArrayTags$1[float64Tag$1] = +typedArrayTags$1[int8Tag$1] = typedArrayTags$1[int16Tag$1] = +typedArrayTags$1[int32Tag$1] = typedArrayTags$1[uint8Tag$1] = +typedArrayTags$1[uint8ClampedTag$1] = typedArrayTags$1[uint16Tag$1] = +typedArrayTags$1[uint32Tag$1] = true; +typedArrayTags$1[argsTag$4] = typedArrayTags$1[arrayTag$2] = +typedArrayTags$1[arrayBufferTag$2] = typedArrayTags$1[boolTag$2] = +typedArrayTags$1[dataViewTag$3] = typedArrayTags$1[dateTag$2] = +typedArrayTags$1[errorTag$2] = typedArrayTags$1[funcTag$3] = +typedArrayTags$1[mapTag$3] = typedArrayTags$1[numberTag$3] = +typedArrayTags$1[objectTag$5] = typedArrayTags$1[regexpTag$2] = +typedArrayTags$1[setTag$3] = typedArrayTags$1[stringTag$3] = +typedArrayTags$1[weakMapTag$2] = false; + +/** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ +function baseIsTypedArray$1(value) { + return isObjectLike$1(value) && + isLength$1(value.length) && !!typedArrayTags$1[baseGetTag$1(value)]; +} + +/** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ +function baseUnary$1(func) { + return function(value) { + return func(value); + }; +} + +/** Detect free variable `exports`. */ +var freeExports$5 = typeof exports == 'object' && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule$5 = freeExports$5 && typeof module == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports$5 = freeModule$5 && freeModule$5.exports === freeExports$5; + +/** Detect free variable `process` from Node.js. */ +var freeProcess$1 = moduleExports$5 && freeGlobal$1.process; + +/** Used to access faster Node.js helpers. */ +var nodeUtil$1 = (function() { + try { + // Use `util.types` for Node.js 10+. + var types = freeModule$5 && freeModule$5.require && freeModule$5.require('util').types; + + if (types) { + return types; + } + + // Legacy `process.binding('util')` for Node.js < 10. + return freeProcess$1 && freeProcess$1.binding && freeProcess$1.binding('util'); + } catch (e) {} +}()); + +/* Node.js helper references. */ +var nodeIsTypedArray$1 = nodeUtil$1 && nodeUtil$1.isTypedArray; + +/** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ +var isTypedArray$1 = nodeIsTypedArray$1 ? baseUnary$1(nodeIsTypedArray$1) : baseIsTypedArray$1; + +/** + * Gets the value at `key`, unless `key` is "__proto__" or "constructor". + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ +function safeGet$1(object, key) { + if (key === 'constructor' && typeof object[key] === 'function') { + return; + } + + if (key == '__proto__') { + return; + } + + return object[key]; +} + +/** Used for built-in method references. */ +var objectProto$n = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$i = objectProto$n.hasOwnProperty; + +/** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function assignValue$1(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty$i.call(object, key) && eq$1(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue$1(object, key, value); + } +} + +/** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ +function copyObject$1(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue$1(object, key, newValue); + } else { + assignValue$1(object, key, newValue); + } + } + return object; +} + +/** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ +function baseTimes$1(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER$3 = 9007199254740991; + +/** Used to detect unsigned integer values. */ +var reIsUint$1 = /^(?:0|[1-9]\d*)$/; + +/** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ +function isIndex$1(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER$3 : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint$1.test(value))) && + (value > -1 && value % 1 == 0 && value < length); +} + +/** Used for built-in method references. */ +var objectProto$o = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$j = objectProto$o.hasOwnProperty; + +/** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ +function arrayLikeKeys$1(value, inherited) { + var isArr = isArray$1(value), + isArg = !isArr && isArguments$1(value), + isBuff = !isArr && !isArg && isBuffer$1(value), + isType = !isArr && !isArg && !isBuff && isTypedArray$1(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes$1(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty$j.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex$1(key, length) + ))) { + result.push(key); + } + } + return result; +} + +/** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function nativeKeysIn$1(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; +} + +/** Used for built-in method references. */ +var objectProto$p = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$k = objectProto$p.hasOwnProperty; + +/** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function baseKeysIn$1(object) { + if (!isObject$1(object)) { + return nativeKeysIn$1(object); + } + var isProto = isPrototype$1(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty$k.call(object, key)))) { + result.push(key); + } + } + return result; +} + +/** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ +function keysIn$1(object) { + return isArrayLike$2(object) ? arrayLikeKeys$1(object, true) : baseKeysIn$1(object); +} + +/** + * Converts `value` to a plain object flattening inherited enumerable string + * keyed properties of `value` to own properties of the plain object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {Object} Returns the converted plain object. + * @example + * + * function Foo() { + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.assign({ 'a': 1 }, new Foo); + * // => { 'a': 1, 'b': 2 } + * + * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); + * // => { 'a': 1, 'b': 2, 'c': 3 } + */ +function toPlainObject$1(value) { + return copyObject$1(value, keysIn$1(value)); +} + +/** + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize assigned values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ +function baseMergeDeep$1(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = safeGet$1(object, key), + srcValue = safeGet$1(source, key), + stacked = stack.get(srcValue); + + if (stacked) { + assignMergeValue$1(object, key, stacked); + return; + } + var newValue = customizer + ? customizer(objValue, srcValue, (key + ''), object, source, stack) + : undefined; + + var isCommon = newValue === undefined; + + if (isCommon) { + var isArr = isArray$1(srcValue), + isBuff = !isArr && isBuffer$1(srcValue), + isTyped = !isArr && !isBuff && isTypedArray$1(srcValue); + + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray$1(objValue)) { + newValue = objValue; + } + else if (isArrayLikeObject$1(objValue)) { + newValue = copyArray$1(objValue); + } + else if (isBuff) { + isCommon = false; + newValue = cloneBuffer$1(srcValue, true); + } + else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray$1(srcValue, true); + } + else { + newValue = []; + } + } + else if (isPlainObject$1(srcValue) || isArguments$1(srcValue)) { + newValue = objValue; + if (isArguments$1(objValue)) { + newValue = toPlainObject$1(objValue); + } + else if (!isObject$1(objValue) || isFunction$1(objValue)) { + newValue = initCloneObject$1(srcValue); + } + } + else { + isCommon = false; + } + } + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack['delete'](srcValue); + } + assignMergeValue$1(object, key, newValue); +} + +/** + * The base implementation of `_.merge` without support for multiple sources. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. + * @param {Function} [customizer] The function to customize merged values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ +function baseMerge$1(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor$1(source, function(srcValue, key) { + stack || (stack = new Stack$1); + if (isObject$1(srcValue)) { + baseMergeDeep$1(object, source, key, srcIndex, baseMerge$1, customizer, stack); + } + else { + var newValue = customizer + ? customizer(safeGet$1(object, key), srcValue, (key + ''), object, source, stack) + : undefined; + + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue$1(object, key, newValue); + } + }, keysIn$1); +} + +/** + * This method returns the first argument it receives. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {*} value Any value. + * @returns {*} Returns `value`. + * @example + * + * var object = { 'a': 1 }; + * + * console.log(_.identity(object) === object); + * // => true + */ +function identity$1(value) { + return value; +} + +/** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ +function apply$1(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); +} + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax$1 = Math.max; + +/** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ +function overRest$1(func, start, transform) { + start = nativeMax$1(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax$1(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply$1(func, this, otherArgs); + }; +} + +/** + * Creates a function that returns `value`. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Util + * @param {*} value The value to return from the new function. + * @returns {Function} Returns the new constant function. + * @example + * + * var objects = _.times(2, _.constant({ 'a': 1 })); + * + * console.log(objects); + * // => [{ 'a': 1 }, { 'a': 1 }] + * + * console.log(objects[0] === objects[1]); + * // => true + */ +function constant$1(value) { + return function() { + return value; + }; +} + +/** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ +var baseSetToString$1 = !defineProperty$1 ? identity$1 : function(func, string) { + return defineProperty$1(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant$1(string), + 'writable': true + }); +}; + +/** Used to detect hot functions by number of calls within a span of milliseconds. */ +var HOT_COUNT$1 = 800, + HOT_SPAN$1 = 16; -/** Built-in value references. */ -var symToStringTag$2 = Symbol$1 ? Symbol$1.toStringTag : undefined; +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeNow$1 = Date.now; /** - * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. * * @private - * @param {*} value The value to query. - * @returns {string} Returns the raw `toStringTag`. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. */ -function getRawTag$1(value) { - var isOwn = hasOwnProperty$c.call(value, symToStringTag$2), - tag = value[symToStringTag$2]; +function shortOut$1(func) { + var count = 0, + lastCalled = 0; - try { - value[symToStringTag$2] = undefined; - var unmasked = true; - } catch (e) {} + return function() { + var stamp = nativeNow$1(), + remaining = HOT_SPAN$1 - (stamp - lastCalled); - var result = nativeObjectToString$2.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag$2] = tag; + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT$1) { + return arguments[0]; + } } else { - delete value[symToStringTag$2]; + count = 0; } - } - return result; + return func.apply(undefined, arguments); + }; } -/** Used for built-in method references. */ -var objectProto$g = Object.prototype; - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. */ -var nativeObjectToString$3 = objectProto$g.toString; +var setToString$1 = shortOut$1(baseSetToString$1); /** - * Converts `value` to a string using `Object.prototype.toString`. + * The base implementation of `_.rest` which doesn't validate or coerce arguments. * * @private - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. */ -function objectToString$1(value) { - return nativeObjectToString$3.call(value); +function baseRest$1(func, start) { + return setToString$1(overRest$1(func, start, identity$1), func + ''); } -/** `Object#toString` result references. */ -var nullTag$1 = '[object Null]', - undefinedTag$1 = '[object Undefined]'; - -/** Built-in value references. */ -var symToStringTag$3 = Symbol$1 ? Symbol$1.toStringTag : undefined; - /** - * The base implementation of `getTag` without fallbacks for buggy environments. + * Checks if the given arguments are from an iteratee call. * * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. */ -function baseGetTag$1(value) { - if (value == null) { - return value === undefined ? undefinedTag$1 : nullTag$1; +function isIterateeCall$1(value, index, object) { + if (!isObject$1(object)) { + return false; } - return (symToStringTag$3 && symToStringTag$3 in Object(value)) - ? getRawTag$1(value) - : objectToString$1(value); + var type = typeof index; + if (type == 'number' + ? (isArrayLike$2(object) && isIndex$1(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq$1(object[index], value); + } + return false; } /** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ +function createAssigner$1(assigner) { + return baseRest$1(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + if (guard && isIterateeCall$1(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); +} + +/** + * This method is like `_.assign` except that it recursively merges own and + * inherited enumerable string keyed properties of source objects into the + * destination object. Source properties that resolve to `undefined` are + * skipped if a destination value exists. Array and plain object properties + * are merged recursively. Other objects and value types are overridden by + * assignment. Source objects are applied from left to right. Subsequent + * sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object`. * * @static * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @since 0.5.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. * @example * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true + * var object = { + * 'a': [{ 'b': 2 }, { 'd': 4 }] + * }; * - * _.isObjectLike(_.noop); - * // => false + * var other = { + * 'a': [{ 'c': 3 }, { 'e': 5 }] + * }; * - * _.isObjectLike(null); - * // => false + * _.merge(object, other); + * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } */ -function isObjectLike$1(value) { - return value != null && typeof value == 'object'; +var merge$1 = createAssigner$1(function(object, source, srcIndex) { + baseMerge$1(object, source, srcIndex); +}); + +// break it out on its own because + +/** + * previously we already make sure the order of the namespaces + * and attach the auth client to it + * @param {array} promises array of unresolved promises + * @param {boolean} asObject if true then merge the result object + * @return {object} promise resolved with the array of promises resolved results + */ +function chainPromises(promises, asObject) { + if ( asObject === void 0 ) asObject = false; + + return promises.reduce(function (promiseChain, currentTask) { return ( + promiseChain.then(function (chainResults) { return ( + currentTask.then(function (currentResult) { return ( + asObject === false ? chainResults.concat( [currentResult]) : merge$1(chainResults, currentResult) + ); }) + ); }) + ); }, Promise.resolve( + asObject === false ? [] : (isPlainObject$1(asObject) ? asObject : {}) + )) +} + +/** + * Because the nsps can be throw away so it doesn't matter the scope + * this will get reuse again + * @NOTE when we enable the standalone method this sequence will not change + * only call and reload + * @param {object} opts configuration + * @param {object} nspMap from contract + * @param {string|null} token whether we have the token at run time + * @return {promise} resolve the nsps namespace with namespace as key + */ +var createNspAction$1 = function(opts, nspMap, token) { + var log = opts.log; + var publicNamespace = nspMap.publicNamespace; + var namespaces = nspMap.namespaces; + log("createNspAction", 'publicNamespace', publicNamespace, 'namespaces', namespaces); + + if (opts.enableAuth) { + return chainPromises( + namespaces.map(function (namespace, i) { + if (i === 0) { + if (token) { + opts.token = token; + log('create createNspAuthClient at run time'); + return createNspAuthClient(namespace, opts) + } + return Promise.resolve(false) + } + return createNspClient(namespace, opts) + }) + ) + .then(function (results) { return results.map(function (result, i) { + var obj; + + return (( obj = {}, obj[namespaces[i]] = result, obj )); + }) + .reduce(function (a, b) { return Object.assign(a, b); }, {}); } + ) + } + + return createNspClient(false, opts) + .then(function (nsp) { + var obj; + + return (( obj = {}, obj[publicNamespace] = nsp, obj )); + }) +}; + +// @BUG when call disconnected + +/** + * create a login event handler + * @param {object} opts configurations + * @param {object} nspMap contain all the required info + * @param {object} ee event emitter + * @return {void} + */ +function loginEventHandler(opts, nspMap, ee) { + var log = opts.log; + var namespaces = nspMap.namespaces; + + ee.$only(LOGIN_EVENT_NAME$1, function loginEventHandlerCallback(tokenFromLoginAction) { + + log('createClient LOGIN_EVENT_NAME $only handler'); + + clearMainEmitEvt(ee, namespaces); + // console.log('LOGIN_EVENT_NAME', token) + var newNsps = createNspAction(opts, nspMap, tokenFromLoginAction); + // rebind it + Reflect.apply( + clientEventHandler, // @NOTE is this the problem that cause the hang up? + null, + args.concat([newNsps.namespaces, newNsps.nsps]) + ); + }); } // bunch of generic helpers @@ -8109,7 +10339,7 @@ var inArray$2 = function (arr, value) { return !!arr.filter(function (a) { retur * @param {boolean} [t=true] or throw * @return {*} json object on success */ -var parseJson = function(n, t) { +var parseJson$1 = function(n, t) { if ( t === void 0 ) t=true; try { @@ -8154,11 +10384,11 @@ var createEvt$1 = function () { * @param {*} n input * @return {object} correct JSON object */ -var toJson = function (n) { +var toJson$1 = function (n) { if (typeof n === 'string') { - return parseJson(n) + return parseJson$1(n) } - return parseJson(JSON.stringify(n)) + return parseJson$1(JSON.stringify(n)) }; // generic placeholder function @@ -8247,7 +10477,7 @@ var JsonqlError$2 = /*@__PURE__*/(function (Error) { * @param {boolean} sec return in second or not * @return {number} timestamp */ -var timestamp = function (sec) { +var timestamp$1 = function (sec) { if ( sec === void 0 ) sec = false; var time = Date.now(); @@ -8255,7 +10485,7 @@ var timestamp = function (sec) { }; /** `Object#toString` result references. */ -var stringTag$3 = '[object String]'; +var stringTag$4 = '[object String]'; /** * Checks if `value` is classified as a `String` primitive or object. @@ -8276,7 +10506,7 @@ var stringTag$3 = '[object String]'; */ function isString$3(value) { return typeof value == 'string' || - (!isArray$1(value) && isObjectLike$1(value) && baseGetTag$1(value) == stringTag$3); + (!isArray$1(value) && isObjectLike$1(value) && baseGetTag$1(value) == stringTag$4); } // ported from jsonql-params-validator @@ -8285,11 +10515,11 @@ function isString$3(value) { * @param {*} args arguments to send *@return {object} formatted payload */ -var formatPayload = function (args) { +var formatPayload$1 = function (args) { var obj; return ( - ( obj = {}, obj[QUERY_ARG_NAME] = args, obj ) + ( obj = {}, obj[QUERY_ARG_NAME$1] = args, obj ) ); }; @@ -8299,10 +10529,10 @@ var formatPayload = function (args) { * @param {*} payload * @return {object} delierable */ -function createDeliverable(resolverName, payload) { +function createDeliverable$1(resolverName, payload) { var obj; - return ( obj = {}, obj[resolverName] = payload, obj[TIMESTAMP_PARAM_NAME] = [ timestamp() ], obj ) + return ( obj = {}, obj[resolverName] = payload, obj[TIMESTAMP_PARAM_NAME$1] = [ timestamp$1() ], obj ) } /** @@ -8311,16 +10541,16 @@ function createDeliverable(resolverName, payload) { * @param {boolean} [jsonp = false] add v1.3.0 to koa * @return {object} formatted argument */ -function createQuery(resolverName, args, jsonp) { +function createQuery$1(resolverName, args, jsonp) { if ( args === void 0 ) args = []; if ( jsonp === void 0 ) jsonp = false; if (isString$3(resolverName) && isArray$1(args)) { - var payload = formatPayload(args); + var payload = formatPayload$1(args); if (jsonp === true) { return payload } - return createDeliverable(resolverName, payload) + return createDeliverable$1(resolverName, payload) } throw new JsonqlValidationError$1("[createQuery] expect resolverName to be string and args to be array!", { resolverName: resolverName, args: args }) } @@ -8329,32 +10559,32 @@ function createQuery(resolverName, args, jsonp) { * string version of the createQuery * @return {string} */ -function createQueryStr(resolverName, args, jsonp) { +function createQueryStr$1(resolverName, args, jsonp) { if ( args === void 0 ) args = []; if ( jsonp === void 0 ) jsonp = false; - return JSON.stringify(createQuery(resolverName, args, jsonp)) + return JSON.stringify(createQuery$1(resolverName, args, jsonp)) } // There are the socket related methods ported back from -var PAYLOAD_NOT_DECODED_ERR = 'payload can not decoded'; -var WS_KEYS = [ - WS_REPLY_TYPE, - WS_EVT_NAME, - WS_DATA_NAME +var PAYLOAD_NOT_DECODED_ERR$1 = 'payload can not decoded'; +var WS_KEYS$1 = [ + WS_REPLY_TYPE$1, + WS_EVT_NAME$1, + WS_DATA_NAME$1 ]; /** * @param {string|object} payload should be string when reply but could be transformed * @return {boolean} true is OK */ -var isWsReply = function (payload) { - var json = isString$3(payload) ? toJson(payload) : payload; +var isWsReply$1 = function (payload) { + var json = isString$3(payload) ? toJson$1(payload) : payload; var data = json.data; if (data) { - var result = WS_KEYS.filter(function (key) { return isObjectHasKey$2(data, key); }); - return (result.length === WS_KEYS.length) ? data : false + var result = WS_KEYS$1.filter(function (key) { return isObjectHasKey$2(data, key); }); + return (result.length === WS_KEYS$1.length) ? data : false } return false }; @@ -8364,24 +10594,24 @@ var isWsReply = function (payload) { * @param {function} [cb=nil] this is for extracting the TS field or when it's error * @return {object} false on failed */ -var extractWsPayload = function (payload, cb) { +var extractWsPayload$1 = function (payload, cb) { if ( cb === void 0 ) cb = nil$1; try { - var json = toJson(payload); + var json = toJson$1(payload); // now handle the data var _data; - if ((_data = isWsReply(json)) !== false) { + if ((_data = isWsReply$1(json)) !== false) { // note the ts property is on its own - cb(TIMESTAMP_PARAM_NAME, json[TIMESTAMP_PARAM_NAME]); + cb(TIMESTAMP_PARAM_NAME$1, json[TIMESTAMP_PARAM_NAME$1]); return { - data: toJson(_data[WS_DATA_NAME]), - resolverName: _data[WS_EVT_NAME], - type: _data[WS_REPLY_TYPE] + data: toJson$1(_data[WS_DATA_NAME$1]), + resolverName: _data[WS_EVT_NAME$1], + type: _data[WS_REPLY_TYPE$1] } } - throw new JsonqlError$2(PAYLOAD_NOT_DECODED_ERR, payload) + throw new JsonqlError$2(PAYLOAD_NOT_DECODED_ERR$1, payload) } catch(e) { return cb(ERROR_KEY$1, e) } @@ -8413,9 +10643,12 @@ var errorTypeHandler = function (ee, namespace, resolverName, json) { /** * Handle the logout event when it's enableAuth * @param {object} ee eventEmitter + * @param {object} ws the WebSocket instance * @return {void} */ -var logoutEventHandler = function (ee) { +var logoutEventHandler = function (ee, ws) { + // @TODO need to issue the logout callback here + // listen to the LOGOUT_EVENT_NAME when this is a private nsp ee.$on(LOGOUT_EVENT_NAME$1, function closeEvtHandler() { try { @@ -8436,7 +10669,7 @@ var logoutEventHandler = function (ee) { * @param {object} opts configuration * @return {object} promise resolve after the onopen event */ -function socketEventHandler(namespace, ws, ee, isPrivate, opts) { +function bindSocketEventHandler(namespace, ws, ee, isPrivate, opts) { var log = opts.log; log("log test, isPrivate:", isPrivate); @@ -8461,7 +10694,7 @@ function socketEventHandler(namespace, ws, ee, isPrivate, opts) { */ function wsMainOnEvtHandler(resolverName, args) { - var payload = createQueryStr(resolverName, args); + var payload = createQueryStr$1(resolverName, args); log('ws.onopen.send', resolverName, args, payload); ws.send(payload); @@ -8478,7 +10711,7 @@ function socketEventHandler(namespace, ws, ee, isPrivate, opts) { // log(`ws.onmessage raw payload`, payload) // @TODO the payload actually contain quite a few things - is that changed? // type: message, data: data_send_from_server - var json = extractWsPayload(payload.data); + var json = extractWsPayload$1(payload.data); var resolverName = json.resolverName; var type = json.type; @@ -8528,7 +10761,7 @@ function socketEventHandler(namespace, ws, ee, isPrivate, opts) { }; if (isPrivate) { - logoutEventHandler(ee); + logoutEventHandler(ee, ws); } } @@ -8543,25 +10776,21 @@ function socketEventHandler(namespace, ws, ee, isPrivate, opts) { */ function createNsp(opts, nspMap, ee) { // arguments for clientEventHandler - var args = [opts, nspMap, ee, socketEventHandler]; + var args = [opts, nspMap, ee, bindSocketEventHandler]; // now create the nsps // const { namespaces } = nspMap var token = opts.token; - var log = opts.log; - var ref = createNspAction$1(opts, nspMap, token); - var nsps = ref.nsps; - args.push(nsps); - // log(`argument length`, args.length, args) - - // binding the listeners - and it will listen to LOGOUT event - // to unbind itself, and the above call will bind it again - Reflect.apply(clientEventHandler$1, null, args); - // setup listener for the login event - if (opts.enableAuth) { - loginEventHandler(opts, nspMap, ee); - } - // return what input - return { opts: opts, nspMap: nspMap, ee: ee } + + return createNspAction$1(opts, nspMap, token) + .then(function (nsps) { + args.push(nsps); + Reflect.apply(clientEventHandler$1, null, args); + if (opts.enableAuth) { + loginEventHandler(opts, nspMap, ee); + } + // return what input + return { opts: opts, nspMap: nspMap, ee: ee } + }) } // breaking up the create-nsp.js file @@ -8574,10 +10803,6 @@ function createNsp(opts, nspMap, ee) { * @return {function} the wsClientResolver */ function bindFrameworkToJsonql(frameworkModule) { - - var nspClient = initWebSocketClient(frameworkModule); - var nspAuthClient = initWebSocketClient(frameworkModule, true); - /** * wsClientResolver * @param {object} opts configuration @@ -8586,8 +10811,9 @@ function bindFrameworkToJsonql(frameworkModule) { * @return {object} passing the same 3 input out with additional in the opts */ return function createClientBindingAction(opts, nspMap, ee) { - opts.nspClient = nspClient; - opts.nspAuthClient = nspAuthClient; + + opts[NSP_CLIENT] = initWebSocketClient(frameworkModule); + opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true); // @1.0.7 remove later once everything fixed var log = opts.log; log("bindFrameworkToJsonql", ee.name, nspMap); diff --git a/packages/@jsonql/ws/main.js.map b/packages/@jsonql/ws/main.js.map index 41bd6bb4..6dba290a 100644 --- a/packages/@jsonql/ws/main.js.map +++ b/packages/@jsonql/ws/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","sources":["node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/lodash-es/_arrayMap.js","../../ws-client-core/node_modules/lodash-es/isArray.js","../../ws-client-core/node_modules/lodash-es/_objectToString.js","../../ws-client-core/node_modules/lodash-es/isObjectLike.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-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/lodash-es/_overArg.js","../../ws-client-core/node_modules/jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/jsonql-params-validator/src/validator.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/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-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-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/node_modules/jsonql-utils/src/generic.js","../../ws-client-core/node_modules/jsonql-utils/src/contract.js","../../ws-client-core/node_modules/jsonql-utils/src/namespace.js","../../ws-client-core/src/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-send-method.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/setup-intercom.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/share/create-nsp-clients.js","../../ws-client-core/src/share/trigger-namespaces-on-error.js","../../ws-client-core/src/share/client-event-handler.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.js","src/core/create-nsp/login-event-handler.js","node_modules/lodash-es/isArray.js","node_modules/lodash-es/_objectToString.js","node_modules/lodash-es/isObjectLike.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/create-nsp/socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.js","src/node-ws-client.js"],"sourcesContent":["export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * 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","// 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","/**\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","// 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","// 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","// 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","/**\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","/** 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","// 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","// 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","// 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// generic placeholder function\nexport const nil = () => false\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","// 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.publicNamespace ].join('/'),\n [ base , config.privateNamespace ].join('/')\n ]\n }\n return [ base ]\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","// 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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log))\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/**\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 createNamespaceErrorHandler(client, opts, ee, nspGroup) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the clientitself\n objDefineProps(client, ON_ERROR_FN_NAME, 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 opts,\n ee\n ]\n}\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 createOnReadyHandler(client, opts, ee) {\n return [\n objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n} from './resolver-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 generator(opts, nspMap, ee) {\n\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n ]\n if (opts.enableAuth) {\n args.push(\n createAuthMethods\n )\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n args.push(setupFinalStep)\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n\n return fn(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 { generator } from './core'\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} frameworkSocketEngine \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(frameworkSocketEngine, config) {\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`jsonql-ws-core-client init error`, err)\n })\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} frameworkSocketEngine 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(frameworkSocketEngine, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(opts => wsClientCoreAction(frameworkSocketEngine, opts))\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 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}","// 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\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, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event handler 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 */\nconst notLoginWsHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n log('[notLoginHandler] 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 handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nconst getPrivateNamespace = (namespaces) => (\n namespaces.length > 1 ? namespaces[0] : false\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 */\nconst logoutEvtHandler = (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(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() {\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 handler\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the handler 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 notLoginWsHandler(privateNamespace, ee, opts)\n })\n}\n\n/**\n * A Event handler 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 */\nconst disconnectedHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedHandlerCallback(resolverName, args) {\n log(`[disconnectedHandler] 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 handler, 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 handler, 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 */\nconst disconnectHandler = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() {\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 disconnectedHandler(namespace, ee, opts)\n })\n })\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts \n * @param {object} ee Event Emitter instance\n * @param {function} bindWsHandler binding the ee to ws --> this is the core bit\n * @param {object} nsps namespaced nsp\n * @return {void} nothing\n */\nexport function clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) {\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 let isPrivate = false\n let hasPrivate = false\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run in order here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace\n if (!hasPrivate) {\n hasPrivate = isPrivate\n }\n // log(namespace, ' --> nsps --> ', nsps[namespace])\n if (nsps[namespace]) {\n\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n \n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n Reflect.apply(bindSocketEventHandler, null, args)\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 notLoginWsHandler(namespace, ee, opts)\n }\n })\n // logout event handler \n if (hasPrivate) {\n log(`Has private and add logoutEvtHandler`)\n logoutEvtHandler(nsps, namespaces, ee, opts)\n }\n // finally the disconnect event handlers\n disconnectHandler(nsps, namespaces, ee, opts) \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'\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 * @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 */\nfunction initWebSocketClient(WebSocket, auth = false) {\n if (auth === false) {\n return function createWsClient(url) {\n return new WebSocket(fixWss(url))\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 * @return {object} ws instance\n */\n return function createWsAuthClient(url, token) {\n const ws_url = fixWss(url)\n // console.log('what happen here?', url, ws_url, token)\n const uri = token && typeof token === 'string' ? `${ws_url}?${TOKEN_PARAM_NAME}=${token}` : ws_url\n try {\n return new WebSocket(uri)\n } catch(e) {\n console.error('WebSocket Connection Error', e)\n return false\n }\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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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 for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","// 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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @return {void}\n */\nconst logoutEventHandler = (ee) => {\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() {\n try {\n log('terminate ws connection')\n ws.terminate()\n } catch(e) {\n console.error('ws.terminate error', e)\n }\n })\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 socketEventHandler(namespace, ws, ee, isPrivate, opts) {\n const { log } = opts\n\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventHandler(ee)\n }\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventHandler } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { socketEventHandler } from './socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // arguments for clientEventHandler\n const args = [opts, nspMap, ee, socketEventHandler]\n // now create the nsps\n // const { namespaces } = nspMap\n const { token, log } = opts\n const { nsps } = createNspAction(opts, nspMap, token)\n args.push(nsps)\n // log(`argument length`, args.length, args)\n\n // binding the listeners - and it will listen to LOGOUT event\n // to unbind itself, and the above call will bind it again\n Reflect.apply(clientEventHandler, null, args)\n // setup listener for the login event\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\n\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\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 const nspClient = initWebSocketClient(frameworkModule)\n const nspAuthClient = initWebSocketClient(frameworkModule, true)\n\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 opts.nspClient = nspClient\n opts.nspAuthClient = nspAuthClient \n // @1.0.7 remove later once everything fixed \n const { log } = opts\n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ No newline at end of file +{"version":3,"file":"main.js","sources":["node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/lodash-es/_arrayMap.js","../../ws-client-core/node_modules/lodash-es/isArray.js","../../ws-client-core/node_modules/lodash-es/_objectToString.js","../../ws-client-core/node_modules/lodash-es/isObjectLike.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-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/lodash-es/_overArg.js","../../ws-client-core/node_modules/jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/jsonql-params-validator/src/validator.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/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-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-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/node_modules/jsonql-utils/src/generic.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/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-send-method.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/setup-intercom.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/share/create-nsp-clients.js","../../ws-client-core/src/share/trigger-namespaces-on-error.js","../../ws-client-core/src/share/client-event-handler.js","../../ws-client-core/src/share/intercom-methods.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.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/login-event-handler.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/create-nsp/bind-socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.js","src/node-ws-client.js"],"sourcesContent":["export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * 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","// 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","/**\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","// 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","// 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","// 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","/**\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","/** 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","// 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","// 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","// 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// generic placeholder function\nexport const nil = () => false\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.publicNamespace ].join('/'),\n [ base , config.privateNamespace ].join('/')\n ]\n }\n return [ base ]\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/**\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","// 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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log))\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/**\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 createNamespaceErrorHandler(client, opts, ee, nspGroup) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the clientitself\n objDefineProps(client, ON_ERROR_FN_NAME, 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 opts,\n ee\n ]\n}\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 createOnReadyHandler(client, opts, ee) {\n return [\n objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n} from './resolver-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 generator(opts, nspMap, ee) {\n\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n ]\n if (opts.enableAuth) {\n args.push(\n createAuthMethods\n )\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n args.push(setupFinalStep)\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n\n return fn(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 { generator } from './core'\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} frameworkSocketEngine \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(frameworkSocketEngine, config) {\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`jsonql-ws-core-client init error`, err)\n })\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} frameworkSocketEngine 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(frameworkSocketEngine, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(opts => wsClientCoreAction(frameworkSocketEngine, opts))\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 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}","// 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\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, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event handler 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 */\nconst notLoginWsHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n log('[notLoginHandler] 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 handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nconst getPrivateNamespace = (namespaces) => (\n namespaces.length > 1 ? namespaces[0] : false\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 */\nconst logoutEvtHandler = (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(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() {\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 handler\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the handler 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 notLoginWsHandler(privateNamespace, ee, opts)\n })\n}\n\n/**\n * A Event handler 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 */\nconst disconnectedHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedHandlerCallback(resolverName, args) {\n log(`[disconnectedHandler] 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 handler, 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 handler, 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 */\nconst disconnectHandler = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() {\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 disconnectedHandler(namespace, ee, opts)\n })\n })\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts \n * @param {object} ee Event Emitter instance\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 clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) {\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 let isPrivate = false\n let hasPrivate = false\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run in order here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace\n if (!hasPrivate) {\n hasPrivate = isPrivate\n }\n // log(namespace, ' --> nsps --> ', nsps[namespace])\n if (nsps[namespace]) {\n\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n Reflect.apply(bindSocketEventHandler, null, args)\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 notLoginWsHandler(namespace, ee, opts)\n }\n })\n // logout event handler \n if (hasPrivate) {\n log(`Has private and add logoutEvtHandler`)\n logoutEvtHandler(nsps, namespaces, ee, opts)\n }\n // finally the disconnect event handlers\n disconnectHandler(nsps, namespaces, ee, opts) \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 * 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 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 json = toJson(payload)\n const result = extractWsPayload(json)\n if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\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 createInitPing, \n extractPingResult, \n createIntercomPayload \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 // terminate the client \n ws.terminate()\n // return the new one with csrf header\n resolver(new WebSocket(url, Object.assign(wsOptions, header)))\n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\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 = false) {\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 \n return new Promise((resolver, rejecter) => {\n const _url = fixWss(url)\n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\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\n return new Promise((resolver, rejecter) => {\n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\n }\n}\n\nexport { initWebSocketClient }","/** 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","// @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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nconst logoutEventHandler = (ee, ws) => {\n // @TODO need to issue the logout callback here\n\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() {\n try {\n log('terminate ws connection')\n ws.terminate()\n } catch(e) {\n console.error('ws.terminate error', e)\n }\n })\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\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventHandler(ee, ws)\n }\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventHandler } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // arguments for clientEventHandler\n const args = [opts, nspMap, ee, bindSocketEventHandler]\n // now create the nsps\n // const { namespaces } = nspMap\n const { token } = opts\n\n return createNspAction(opts, nspMap, token)\n .then(nsps => {\n args.push(nsps)\n Reflect.apply(clientEventHandler, null, args)\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n }) \n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\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 * @return {object} passing the same 3 input out with additional in the opts\n */\n return function createClientBindingAction(opts, nspMap, ee) {\n\n opts[NSP_CLIENT] = initWebSocketClient(frameworkModule)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true) \n // @1.0.7 remove later once everything fixed \n const { log } = opts\n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ No newline at end of file -- Gitee From abaa8802d74dbdbc516d981e529dac41e388e134 Mon Sep 17 00:00:00 2001 From: joelchu Date: Mon, 16 Mar 2020 22:49:06 +0800 Subject: [PATCH 07/66] update deps --- packages/ws-server-core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ws-server-core/package.json b/packages/ws-server-core/package.json index ef1adf75..581787bf 100644 --- a/packages/ws-server-core/package.json +++ b/packages/ws-server-core/package.json @@ -31,7 +31,7 @@ "debug": "^4.1.1", "esm": "^3.2.25", "fs-extra": "^8.1.0", - "jsonql-constants": "^2.0.2", + "jsonql-constants": "^2.0.4", "jsonql-errors": "^1.2.1", "jsonql-jwt": "^1.3.10", "jsonql-params-validator": "^1.6.1", -- Gitee From bc06c69497fd6b0d719f63a6fd5b4d6bcb3b7e7d Mon Sep 17 00:00:00 2001 From: joelchu Date: Mon, 16 Mar 2020 22:51:11 +0800 Subject: [PATCH 08/66] The test is somewhat breaking up --- packages/ws-server/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json index 4ef0fa9d..95684555 100755 --- a/packages/ws-server/package.json +++ b/packages/ws-server/package.json @@ -33,7 +33,7 @@ "dependencies": { "colors": "^1.4.0", "debug": "^4.1.1", - "jsonql-constants": "^2.0.3", + "jsonql-constants": "^2.0.4", "jsonql-utils": "^1.2.0", "jsonql-ws-server-core": "^0.7.6", "ws": "^7.2.3" -- Gitee From ad0fb8bc931c9a63ef2ec03019c0c7ade714d5c6 Mon Sep 17 00:00:00 2001 From: joelchu Date: Mon, 16 Mar 2020 22:56:09 +0800 Subject: [PATCH 09/66] add the intercom to the logout --- .../ws/src/core/create-nsp/bind-socket-event-handler.js | 7 ++++--- packages/@jsonql/ws/src/core/modules.js | 6 ++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/@jsonql/ws/src/core/create-nsp/bind-socket-event-handler.js b/packages/@jsonql/ws/src/core/create-nsp/bind-socket-event-handler.js index 5de5aecb..4aaea8f3 100644 --- a/packages/@jsonql/ws/src/core/create-nsp/bind-socket-event-handler.js +++ b/packages/@jsonql/ws/src/core/create-nsp/bind-socket-event-handler.js @@ -17,7 +17,8 @@ import { extractWsPayload } from 'jsonql-utils/module' import { - handleNamespaceOnError + handleNamespaceOnError, + createIntercomPayload } from '../modules' /** @@ -48,8 +49,8 @@ const errorTypeHandler = (ee, namespace, resolverName, json) => { * @return {void} */ const logoutEventHandler = (ee, ws) => { - // @TODO need to issue the logout callback here - + // @TODO we need find a way to get the userdata + ws.send(createIntercomPayload(LOGOUT_EVENT_NAME)) // listen to the LOGOUT_EVENT_NAME when this is a private nsp ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() { try { diff --git a/packages/@jsonql/ws/src/core/modules.js b/packages/@jsonql/ws/src/core/modules.js index ba826144..c16472ee 100644 --- a/packages/@jsonql/ws/src/core/modules.js +++ b/packages/@jsonql/ws/src/core/modules.js @@ -25,7 +25,8 @@ import { createCombineClient, createInitPing, - extractPingResult + extractPingResult, + createIntercomPayload } from '../../../../ws-client-core/index' // 'jsonql-ws-client-core' // export @@ -54,5 +55,6 @@ export { createCombineClient, createInitPing, - extractPingResult + extractPingResult, + createIntercomPayload } \ No newline at end of file -- Gitee From 9b86db2451f6bc622df3951ccad464875f0ae42d Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 07:55:03 +0800 Subject: [PATCH 10/66] update the order of the group by namesapce --- packages/@jsonql/ws/main.js | 27 ++++++++++++++++--- packages/@jsonql/ws/main.js.map | 2 +- packages/utils/browser.js | 2 +- packages/utils/main.js | 2 +- packages/utils/src/namespace.js | 5 ++-- .../ws-client-core/src/options/defaults.js | 10 +++++-- 6 files changed, 38 insertions(+), 10 deletions(-) diff --git a/packages/@jsonql/ws/main.js b/packages/@jsonql/ws/main.js index 0972f5dd..cd77b7fa 100644 --- a/packages/@jsonql/ws/main.js +++ b/packages/@jsonql/ws/main.js @@ -716,6 +716,7 @@ var TIMESTAMP_PARAM_NAME = 'TS'; // for contract-cli var KEY_WORD = 'continue'; var PUBLIC_KEY = 'public'; +var PRIVATE_KEY = 'private'; var LOGIN_FN_NAME = 'login'; // export const ISSUER_NAME = LOGIN_NAME // legacy issue need to replace them later var LOGOUT_FN_NAME = 'logout'; @@ -7620,7 +7621,10 @@ var wsCoreConstProps = { nspClient: null, nspAuthClient: null, // contructed path - wssPath: '' + wssPath: '', + // for generate the namespaces + publicNamespace: PUBLIC_KEY, + privateNamespace: PRIVATE_KEY }; // create options @@ -8002,6 +8006,23 @@ function extractPingResult(payload) { throw new JsonqlError$1('extractPingResult', CSRF_HEADER_NOT_EXIST_ERR) } + +/** + * Create a generic intercom method + * @param {string} type the event type + * @param {array} args if any + * @return {string} formatted payload to send + */ +function createIntercomPayload(type) { + var args = [], len = arguments.length - 1; + while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; + + var ts = timestamp(); + var payload = [type].concat(args); + payload.push(ts); + return createQueryStr(INTERCOM_RESOLVER_NAME, payload) +} + /* base.js */ var ERROR_KEY$1 = 'error'; var QUERY_ARG_NAME$1 = 'args'; @@ -10647,8 +10668,8 @@ var errorTypeHandler = function (ee, namespace, resolverName, json) { * @return {void} */ var logoutEventHandler = function (ee, ws) { - // @TODO need to issue the logout callback here - + // @TODO we need find a way to get the userdata + ws.send(createIntercomPayload(LOGOUT_EVENT_NAME$1)); // listen to the LOGOUT_EVENT_NAME when this is a private nsp ee.$on(LOGOUT_EVENT_NAME$1, function closeEvtHandler() { try { diff --git a/packages/@jsonql/ws/main.js.map b/packages/@jsonql/ws/main.js.map index 6dba290a..2865fb13 100644 --- a/packages/@jsonql/ws/main.js.map +++ b/packages/@jsonql/ws/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","sources":["node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/lodash-es/_arrayMap.js","../../ws-client-core/node_modules/lodash-es/isArray.js","../../ws-client-core/node_modules/lodash-es/_objectToString.js","../../ws-client-core/node_modules/lodash-es/isObjectLike.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-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/lodash-es/_overArg.js","../../ws-client-core/node_modules/jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/jsonql-params-validator/src/validator.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/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-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-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/node_modules/jsonql-utils/src/generic.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/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-send-method.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/setup-intercom.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/share/create-nsp-clients.js","../../ws-client-core/src/share/trigger-namespaces-on-error.js","../../ws-client-core/src/share/client-event-handler.js","../../ws-client-core/src/share/intercom-methods.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.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/login-event-handler.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/create-nsp/bind-socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.js","src/node-ws-client.js"],"sourcesContent":["export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * 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","// 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","/**\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","// 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","// 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","// 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","/**\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","/** 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","// 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","// 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","// 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// generic placeholder function\nexport const nil = () => false\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.publicNamespace ].join('/'),\n [ base , config.privateNamespace ].join('/')\n ]\n }\n return [ base ]\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/**\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","// 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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log))\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/**\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 createNamespaceErrorHandler(client, opts, ee, nspGroup) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the clientitself\n objDefineProps(client, ON_ERROR_FN_NAME, 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 opts,\n ee\n ]\n}\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 createOnReadyHandler(client, opts, ee) {\n return [\n objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n} from './resolver-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 generator(opts, nspMap, ee) {\n\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n ]\n if (opts.enableAuth) {\n args.push(\n createAuthMethods\n )\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n args.push(setupFinalStep)\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n\n return fn(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 { generator } from './core'\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} frameworkSocketEngine \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(frameworkSocketEngine, config) {\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`jsonql-ws-core-client init error`, err)\n })\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} frameworkSocketEngine 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(frameworkSocketEngine, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(opts => wsClientCoreAction(frameworkSocketEngine, opts))\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 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}","// 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\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, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event handler 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 */\nconst notLoginWsHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n log('[notLoginHandler] 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 handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nconst getPrivateNamespace = (namespaces) => (\n namespaces.length > 1 ? namespaces[0] : false\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 */\nconst logoutEvtHandler = (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(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() {\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 handler\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the handler 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 notLoginWsHandler(privateNamespace, ee, opts)\n })\n}\n\n/**\n * A Event handler 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 */\nconst disconnectedHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedHandlerCallback(resolverName, args) {\n log(`[disconnectedHandler] 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 handler, 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 handler, 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 */\nconst disconnectHandler = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() {\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 disconnectedHandler(namespace, ee, opts)\n })\n })\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts \n * @param {object} ee Event Emitter instance\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 clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) {\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 let isPrivate = false\n let hasPrivate = false\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run in order here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace\n if (!hasPrivate) {\n hasPrivate = isPrivate\n }\n // log(namespace, ' --> nsps --> ', nsps[namespace])\n if (nsps[namespace]) {\n\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n Reflect.apply(bindSocketEventHandler, null, args)\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 notLoginWsHandler(namespace, ee, opts)\n }\n })\n // logout event handler \n if (hasPrivate) {\n log(`Has private and add logoutEvtHandler`)\n logoutEvtHandler(nsps, namespaces, ee, opts)\n }\n // finally the disconnect event handlers\n disconnectHandler(nsps, namespaces, ee, opts) \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 * 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 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 json = toJson(payload)\n const result = extractWsPayload(json)\n if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\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 createInitPing, \n extractPingResult, \n createIntercomPayload \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 // terminate the client \n ws.terminate()\n // return the new one with csrf header\n resolver(new WebSocket(url, Object.assign(wsOptions, header)))\n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\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 = false) {\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 \n return new Promise((resolver, rejecter) => {\n const _url = fixWss(url)\n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\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\n return new Promise((resolver, rejecter) => {\n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\n }\n}\n\nexport { initWebSocketClient }","/** 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","// @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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nconst logoutEventHandler = (ee, ws) => {\n // @TODO need to issue the logout callback here\n\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() {\n try {\n log('terminate ws connection')\n ws.terminate()\n } catch(e) {\n console.error('ws.terminate error', e)\n }\n })\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\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventHandler(ee, ws)\n }\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventHandler } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // arguments for clientEventHandler\n const args = [opts, nspMap, ee, bindSocketEventHandler]\n // now create the nsps\n // const { namespaces } = nspMap\n const { token } = opts\n\n return createNspAction(opts, nspMap, token)\n .then(nsps => {\n args.push(nsps)\n Reflect.apply(clientEventHandler, null, args)\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n }) \n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\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 * @return {object} passing the same 3 input out with additional in the opts\n */\n return function createClientBindingAction(opts, nspMap, ee) {\n\n opts[NSP_CLIENT] = initWebSocketClient(frameworkModule)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true) \n // @1.0.7 remove later once everything fixed \n const { log } = opts\n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ No newline at end of file +{"version":3,"file":"main.js","sources":["node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/lodash-es/_arrayMap.js","../../ws-client-core/node_modules/lodash-es/isArray.js","../../ws-client-core/node_modules/lodash-es/_objectToString.js","../../ws-client-core/node_modules/lodash-es/isObjectLike.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-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/lodash-es/_overArg.js","../../ws-client-core/node_modules/jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/jsonql-params-validator/src/validator.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/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-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-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/node_modules/jsonql-utils/src/generic.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/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-send-method.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/setup-intercom.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/share/create-nsp-clients.js","../../ws-client-core/src/share/trigger-namespaces-on-error.js","../../ws-client-core/src/share/client-event-handler.js","../../ws-client-core/src/share/intercom-methods.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.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/login-event-handler.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/create-nsp/bind-socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.js","src/node-ws-client.js"],"sourcesContent":["export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * 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","// 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","/**\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","// 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","// 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","// 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","/**\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","/** 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","// 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","// 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","// 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// generic placeholder function\nexport const nil = () => false\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.publicNamespace ].join('/'),\n [ base , config.privateNamespace ].join('/')\n ]\n }\n return [ base ]\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/**\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","// 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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log))\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/**\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 createNamespaceErrorHandler(client, opts, ee, nspGroup) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the clientitself\n objDefineProps(client, ON_ERROR_FN_NAME, 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 opts,\n ee\n ]\n}\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 createOnReadyHandler(client, opts, ee) {\n return [\n objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n} from './resolver-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 generator(opts, nspMap, ee) {\n\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n ]\n if (opts.enableAuth) {\n args.push(\n createAuthMethods\n )\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n args.push(setupFinalStep)\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n\n return fn(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 { generator } from './core'\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} frameworkSocketEngine \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(frameworkSocketEngine, config) {\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`jsonql-ws-core-client init error`, err)\n })\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} frameworkSocketEngine 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(frameworkSocketEngine, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(opts => wsClientCoreAction(frameworkSocketEngine, opts))\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 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}","// 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\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, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event handler 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 */\nconst notLoginWsHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n log('[notLoginHandler] 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 handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nconst getPrivateNamespace = (namespaces) => (\n namespaces.length > 1 ? namespaces[0] : false\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 */\nconst logoutEvtHandler = (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(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() {\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 handler\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the handler 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 notLoginWsHandler(privateNamespace, ee, opts)\n })\n}\n\n/**\n * A Event handler 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 */\nconst disconnectedHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedHandlerCallback(resolverName, args) {\n log(`[disconnectedHandler] 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 handler, 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 handler, 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 */\nconst disconnectHandler = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() {\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 disconnectedHandler(namespace, ee, opts)\n })\n })\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts \n * @param {object} ee Event Emitter instance\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 clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) {\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 let isPrivate = false\n let hasPrivate = false\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run in order here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace\n if (!hasPrivate) {\n hasPrivate = isPrivate\n }\n // log(namespace, ' --> nsps --> ', nsps[namespace])\n if (nsps[namespace]) {\n\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n Reflect.apply(bindSocketEventHandler, null, args)\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 notLoginWsHandler(namespace, ee, opts)\n }\n })\n // logout event handler \n if (hasPrivate) {\n log(`Has private and add logoutEvtHandler`)\n logoutEvtHandler(nsps, namespaces, ee, opts)\n }\n // finally the disconnect event handlers\n disconnectHandler(nsps, namespaces, ee, opts) \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 * 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 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 json = toJson(payload)\n const result = extractWsPayload(json)\n if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\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 createInitPing, \n extractPingResult, \n createIntercomPayload \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 // terminate the client \n ws.terminate()\n // return the new one with csrf header\n resolver(new WebSocket(url, Object.assign(wsOptions, header)))\n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\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 = false) {\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 \n return new Promise((resolver, rejecter) => {\n const _url = fixWss(url)\n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\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\n return new Promise((resolver, rejecter) => {\n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\n }\n}\n\nexport { initWebSocketClient }","/** 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","// @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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError,\n createIntercomPayload\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nconst logoutEventHandler = (ee, ws) => {\n // @TODO we need find a way to get the userdata \n ws.send(createIntercomPayload(LOGOUT_EVENT_NAME))\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() {\n try {\n log('terminate ws connection')\n ws.terminate()\n } catch(e) {\n console.error('ws.terminate error', e)\n }\n })\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\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventHandler(ee, ws)\n }\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventHandler } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // arguments for clientEventHandler\n const args = [opts, nspMap, ee, bindSocketEventHandler]\n // now create the nsps\n // const { namespaces } = nspMap\n const { token } = opts\n\n return createNspAction(opts, nspMap, token)\n .then(nsps => {\n args.push(nsps)\n Reflect.apply(clientEventHandler, null, args)\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n }) \n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\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 * @return {object} passing the same 3 input out with additional in the opts\n */\n return function createClientBindingAction(opts, nspMap, ee) {\n\n opts[NSP_CLIENT] = initWebSocketClient(frameworkModule)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true) \n // @1.0.7 remove later once everything fixed \n const { log } = opts\n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ No newline at end of file diff --git a/packages/utils/browser.js b/packages/utils/browser.js index 62ca9a36..7acc54d7 100644 --- a/packages/utils/browser.js +++ b/packages/utils/browser.js @@ -1,2 +1,2 @@ -!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t=t||self).jsonqlUtils={})}(this,(function(t){"use strict";var r=Array.isArray,e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},n="object"==typeof e&&e&&e.Object===Object&&e,o="object"==typeof self&&self&&self.Object===Object&&self,u=n||o||Function("return this")(),i=u.Symbol,a=Object.prototype,c=a.hasOwnProperty,f=a.toString,s=i?i.toStringTag:void 0;var l=Object.prototype.toString;var p=i?i.toStringTag:void 0;function v(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":p&&p in Object(t)?function(t){var r=c.call(t,s),e=t[s];try{t[s]=void 0;var n=!0}catch(t){}var o=f.call(t);return n&&(r?t[s]=e:delete t[s]),o}(t):function(t){return l.call(t)}(t)}var d,y,h=(d=Object.getPrototypeOf,y=Object,function(t){return d(y(t))});function _(t){return null!=t&&"object"==typeof t}var g=Function.prototype,b=Object.prototype,j=g.toString,m=b.hasOwnProperty,w=j.call(Object);function O(t){if(!_(t)||"[object Object]"!=v(t))return!1;var r=h(t);if(null===r)return!0;var e=m.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&j.call(e)==w}var S=i?i.prototype:void 0,P=S?S.toString:void 0;function N(t){if("string"==typeof t)return t;if(r(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var u=Array(o);++n-1;);return e}(o,u),function(t,r){for(var e=t.length;e--&&E(r,t[e],0)>-1;);return e}(o,u)+1).join("")}var I=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return r(t)?t:[t]},L=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},V=function(t,r){try{var e=Object.keys(t);return I(e,r)}catch(t){return!1}},W=function(t){return L("string"==typeof t?t:JSON.stringify(t))},H=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function Z(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var X=Array.prototype.splice;function Y(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},Y.prototype.set=function(t,r){var e=this.__data__,n=Z(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function rt(t){if(!tt(t))return!1;var r=v(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var et,nt=u["__core-js_shared__"],ot=(et=/[^.]+$/.exec(nt&&nt.keys&&nt.keys.IE_PROTO||""))?"Symbol(src)_1."+et:"";var ut=Function.prototype.toString;var it=/^\[object .+?Constructor\]$/,at=Function.prototype,ct=Object.prototype,ft=at.toString,st=ct.hasOwnProperty,lt=RegExp("^"+ft.call(st).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pt(t){return!(!tt(t)||function(t){return!!ot&&ot in t}(t))&&(rt(t)?lt:it).test(function(t){if(null!=t){try{return ut.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function vt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pt(e)?e:void 0}var dt=vt(u,"Map"),yt=vt(Object,"create");var ht=Object.prototype.hasOwnProperty;var _t=Object.prototype.hasOwnProperty;function gt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Gt(t.length)&&!rt(t)}var It="object"==typeof t&&t&&!t.nodeType&&t,Qt=It&&"object"==typeof module&&module&&!module.nodeType&&module,Lt=Qt&&Qt.exports===It?u.Buffer:void 0,Vt=(Lt?Lt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Ht="object"==typeof t&&t&&!t.nodeType&&t,Kt=Ht&&"object"==typeof module&&module&&!module.nodeType&&module,Zt=Kt&&Kt.exports===Ht&&n.process,Xt=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Zt&&Zt.binding&&Zt.binding("util")}catch(t){}}(),Yt=Xt&&Xt.isTypedArray,tr=Yt?function(t){return function(r){return t(r)}}(Yt):function(t){return _(t)&&Gt(t.length)&&!!Wt[v(t)]};function rr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var er=Object.prototype.hasOwnProperty;function nr(t,r,e){var n=t[r];er.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||Ot(t,r,e)}var or=/^(?:0|[1-9]\d*)$/;function ur(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&or.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(_r);function jr(t,r){return br(function(t,r,e){return r=hr(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,u=hr(n.length-r,0),i=Array(u);++o1?r[n-1]:void 0,u=n>2?r[2]:void 0;for(o=mr.length>3&&"function"==typeof o?(n--,o):void 0,u&&function(t,r,e){if(!tt(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ur(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],u)&&(o=n<3?void 0:o,n=1),t=Object(t);++e0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},t.chainProcessPromises=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return t.then((function(t){return r(t)}))}),Reflect.apply(t,null,e))}},t.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):wr(t,e)}))}))}),Promise.resolve(!1===r?[]:O(r)?r:{}))},t.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("acknowledge_reply",t,r,e)},t.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},t.createMutation=Ur,t.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Ur(t,r,e,n))},t.createQuery=qr,t.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},t.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("emit_reply",t,r,e)},t.createWsReply=Wr,t.dasherize=function(t){return $(t).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},t.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ar("Unknown "+r+" to extract argument from!")}},t.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Pr(e,r);return n}catch(t){throw new Pr(e,t)}},t.extractSocketPart=Tr,t.extractWsPayload=function(t,r){void 0===r&&(r=H);try{var e,n=W(t);if(!1!==(e=Hr(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ar("payload can not decoded",t)}catch(t){return r("error",t)}},t.formatPayload=Jr,t.getCallMethod=function(t){switch(!0){case t===Sr[0]:return"query";case t===Sr[1]:return"mutation";default:return!1}},t.getConfigValue=function(t,r){return r&&O(r)&&t in r?r[t]:void 0},t.getLogger=function(t){var r=[t];return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];try{window&&window.JSONQL_DEBUG&&Reflect.apply(console.info,console,r.concat(t))}catch(t){}}},t.getMutationFromArgs=Gr,t.getMutationFromPayload=function(t){var r=Dr(t,Gr);if(!1!==r)return r;throw new Nr("[getMutationArgs] Payload is malformed!",t)},t.getNamespace=Qr,t.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},t.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Qr(t),o=e?Ir(r):function(t,r){var e,n={};for(var o in t){var u=t[o];n[o]=u}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},t.getQueryFromArgs=Br,t.getQueryFromPayload=function(t){var r=Dr(t,Br);if(!1!==r)return r;throw new Nr("[getQueryArgs] Payload is malformed!",t)},t.getRegex=function(t){switch(!0){case!0===Lr(t):return t;case!0===kr(t):return new RegExp(t);default:return!1}},t.getResolverFromPayload=Mr,t.groupByNamespace=Ir,t.inArray=I,t.injectToFn=function(t,r,e,n){void 0===n&&(n=!1);var o=Or(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t},t.isContract=function(t){return!!function(t){return O(t)&&(V(t,"query")||V(t,"mutation")||V(t,"socket"))}(t)&&t},t.isFunc=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},t.isJsonqlErrorObj=$r,t.isNotEmpty=function(t){return void 0!==t&&!1!==t&&null!==t&&""!==$(t)},t.isObjectHasKey=V,t.isRegExp=Lr,t.isWsReply=Hr,t.logger=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];try{window&&window.DEBUG&&Reflect.apply(console.log,console,t)}catch(t){}},t.nil=H,t.objDefineProps=function(t,r,e,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,r)&&Object.defineProperty(t,r,{set:e,get:null===n?function(){return null}:n}),t},t.objHasProp=Or,t.packError=function(t,r,e,n){var o;void 0===r&&(r="JsonqlError"),void 0===e&&(e=0),void 0===n&&(n="");var u={detail:t,className:r,statusCode:e,message:n};return JSON.stringify(((o={}).error=$r(t)||u,o.TS=[Er()],o))},t.packResult=function(t,e){void 0===e&&(e=!1);var n={};return n.data=t,e&&r(e)&&(e.push(Er()),n.TS=e),JSON.stringify(n)},t.parseJson=L,t.resultHandler=function(t){return V(t,"data")&&!V(t,"error")?t.data:t},t.timestamp=Er,t.toArray=Q,t.toJson=W,t.toPayload=Rr,t.urlParams=xr,Object.defineProperty(t,"__esModule",{value:!0})})); +!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t=t||self).jsonqlUtils={})}(this,(function(t){"use strict";var r=Array.isArray,e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},n="object"==typeof e&&e&&e.Object===Object&&e,o="object"==typeof self&&self&&self.Object===Object&&self,u=n||o||Function("return this")(),i=u.Symbol,a=Object.prototype,c=a.hasOwnProperty,f=a.toString,s=i?i.toStringTag:void 0;var l=Object.prototype.toString;var p=i?i.toStringTag:void 0;function v(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":p&&p in Object(t)?function(t){var r=c.call(t,s),e=t[s];try{t[s]=void 0;var n=!0}catch(t){}var o=f.call(t);return n&&(r?t[s]=e:delete t[s]),o}(t):function(t){return l.call(t)}(t)}var d,y,h=(d=Object.getPrototypeOf,y=Object,function(t){return d(y(t))});function _(t){return null!=t&&"object"==typeof t}var g=Function.prototype,b=Object.prototype,j=g.toString,m=b.hasOwnProperty,w=j.call(Object);function O(t){if(!_(t)||"[object Object]"!=v(t))return!1;var r=h(t);if(null===r)return!0;var e=m.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&j.call(e)==w}var S=i?i.prototype:void 0,P=S?S.toString:void 0;function N(t){if("string"==typeof t)return t;if(r(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var u=Array(o);++n-1;);return e}(o,u),function(t,r){for(var e=t.length;e--&&E(r,t[e],0)>-1;);return e}(o,u)+1).join("")}var I=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return r(t)?t:[t]},L=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},V=function(t,r){try{var e=Object.keys(t);return I(e,r)}catch(t){return!1}},W=function(t){return L("string"==typeof t?t:JSON.stringify(t))},H=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function Z(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var X=Array.prototype.splice;function Y(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},Y.prototype.set=function(t,r){var e=this.__data__,n=Z(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function rt(t){if(!tt(t))return!1;var r=v(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var et,nt=u["__core-js_shared__"],ot=(et=/[^.]+$/.exec(nt&&nt.keys&&nt.keys.IE_PROTO||""))?"Symbol(src)_1."+et:"";var ut=Function.prototype.toString;var it=/^\[object .+?Constructor\]$/,at=Function.prototype,ct=Object.prototype,ft=at.toString,st=ct.hasOwnProperty,lt=RegExp("^"+ft.call(st).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pt(t){return!(!tt(t)||function(t){return!!ot&&ot in t}(t))&&(rt(t)?lt:it).test(function(t){if(null!=t){try{return ut.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function vt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pt(e)?e:void 0}var dt=vt(u,"Map"),yt=vt(Object,"create");var ht=Object.prototype.hasOwnProperty;var _t=Object.prototype.hasOwnProperty;function gt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Gt(t.length)&&!rt(t)}var It="object"==typeof t&&t&&!t.nodeType&&t,Qt=It&&"object"==typeof module&&module&&!module.nodeType&&module,Lt=Qt&&Qt.exports===It?u.Buffer:void 0,Vt=(Lt?Lt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Ht="object"==typeof t&&t&&!t.nodeType&&t,Kt=Ht&&"object"==typeof module&&module&&!module.nodeType&&module,Zt=Kt&&Kt.exports===Ht&&n.process,Xt=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Zt&&Zt.binding&&Zt.binding("util")}catch(t){}}(),Yt=Xt&&Xt.isTypedArray,tr=Yt?function(t){return function(r){return t(r)}}(Yt):function(t){return _(t)&&Gt(t.length)&&!!Wt[v(t)]};function rr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var er=Object.prototype.hasOwnProperty;function nr(t,r,e){var n=t[r];er.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||Ot(t,r,e)}var or=/^(?:0|[1-9]\d*)$/;function ur(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&or.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(_r);function jr(t,r){return br(function(t,r,e){return r=hr(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,u=hr(n.length-r,0),i=Array(u);++o1?r[n-1]:void 0,u=n>2?r[2]:void 0;for(o=mr.length>3&&"function"==typeof o?(n--,o):void 0,u&&function(t,r,e){if(!tt(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ur(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],u)&&(o=n<3?void 0:o,n=1),t=Object(t);++e0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},t.chainProcessPromises=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return t.then((function(t){return r(t)}))}),Reflect.apply(t,null,e))}},t.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):wr(t,e)}))}))}),Promise.resolve(!1===r?[]:O(r)?r:{}))},t.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("acknowledge_reply",t,r,e)},t.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},t.createMutation=Ur,t.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Ur(t,r,e,n))},t.createQuery=qr,t.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},t.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("emit_reply",t,r,e)},t.createWsReply=Wr,t.dasherize=function(t){return $(t).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},t.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ar("Unknown "+r+" to extract argument from!")}},t.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Pr(e,r);return n}catch(t){throw new Pr(e,t)}},t.extractSocketPart=Tr,t.extractWsPayload=function(t,r){void 0===r&&(r=H);try{var e,n=W(t);if(!1!==(e=Hr(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ar("payload can not decoded",t)}catch(t){return r("error",t)}},t.formatPayload=Jr,t.getCallMethod=function(t){switch(!0){case t===Sr[0]:return"query";case t===Sr[1]:return"mutation";default:return!1}},t.getConfigValue=function(t,r){return r&&O(r)&&t in r?r[t]:void 0},t.getLogger=function(t){var r=[t];return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];try{window&&window.JSONQL_DEBUG&&Reflect.apply(console.info,console,r.concat(t))}catch(t){}}},t.getMutationFromArgs=Gr,t.getMutationFromPayload=function(t){var r=Dr(t,Gr);if(!1!==r)return r;throw new Nr("[getMutationArgs] Payload is malformed!",t)},t.getNamespace=Qr,t.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},t.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Qr(t),o=e?Ir(r):function(t,r){var e,n={};for(var o in t){var u=t[o];n[o]=u}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},t.getQueryFromArgs=Br,t.getQueryFromPayload=function(t){var r=Dr(t,Br);if(!1!==r)return r;throw new Nr("[getQueryArgs] Payload is malformed!",t)},t.getRegex=function(t){switch(!0){case!0===Lr(t):return t;case!0===kr(t):return new RegExp(t);default:return!1}},t.getResolverFromPayload=Mr,t.groupByNamespace=Ir,t.inArray=I,t.injectToFn=function(t,r,e,n){void 0===n&&(n=!1);var o=Or(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t},t.isContract=function(t){return!!function(t){return O(t)&&(V(t,"query")||V(t,"mutation")||V(t,"socket"))}(t)&&t},t.isFunc=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},t.isJsonqlErrorObj=$r,t.isNotEmpty=function(t){return void 0!==t&&!1!==t&&null!==t&&""!==$(t)},t.isObjectHasKey=V,t.isRegExp=Lr,t.isWsReply=Hr,t.logger=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];try{window&&window.DEBUG&&Reflect.apply(console.log,console,t)}catch(t){}},t.nil=H,t.objDefineProps=function(t,r,e,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,r)&&Object.defineProperty(t,r,{set:e,get:null===n?function(){return null}:n}),t},t.objHasProp=Or,t.packError=function(t,r,e,n){var o;void 0===r&&(r="JsonqlError"),void 0===e&&(e=0),void 0===n&&(n="");var u={detail:t,className:r,statusCode:e,message:n};return JSON.stringify(((o={}).error=$r(t)||u,o.TS=[Er()],o))},t.packResult=function(t,e){void 0===e&&(e=!1);var n={};return n.data=t,e&&r(e)&&(e.push(Er()),n.TS=e),JSON.stringify(n)},t.parseJson=L,t.resultHandler=function(t){return V(t,"data")&&!V(t,"error")?t.data:t},t.timestamp=Er,t.toArray=Q,t.toJson=W,t.toPayload=Rr,t.urlParams=xr,Object.defineProperty(t,"__esModule",{value:!0})})); //# sourceMappingURL=browser.js.map diff --git a/packages/utils/main.js b/packages/utils/main.js index 2daf742c..9b7579dc 100644 --- a/packages/utils/main.js +++ b/packages/utils/main.js @@ -1,2 +1,2 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t,r=(t=require("fs"))&&"object"==typeof t&&"default"in t?t.default:t,e=require("path"),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,u="object"==typeof self&&self&&self.Object===Object&&self,a=i||u||Function("return this")(),f=a.Symbol,s=Object.prototype,c=s.hasOwnProperty,h=s.toString,p=f?f.toStringTag:void 0;var l=Object.prototype.toString;var g=f?f.toStringTag:void 0;function y(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":g&&g in Object(t)?function(t){var r=c.call(t,p),e=t[p];try{t[p]=void 0;var n=!0}catch(t){}var o=h.call(t);return n&&(r?t[p]=e:delete t[p]),o}(t):function(t){return l.call(t)}(t)}var v,d,_=(v=Object.getPrototypeOf,d=Object,function(t){return v(d(t))});function b(t){return null!=t&&"object"==typeof t}var w=Function.prototype,m=Object.prototype,A=w.toString,E=m.hasOwnProperty,x=A.call(Object);function j(t){if(!b(t)||"[object Object]"!=y(t))return!1;var r=_(t);if(null===r)return!0;var e=E.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&A.call(e)==x}var P=f?f.prototype:void 0,R=P?P.toString:void 0;function O(t){if("string"==typeof t)return t;if(n(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var i=Array(o);++n-1;);return e}(o,i),function(t,r){for(var e=t.length;e--&&U(r,t[e],0)>-1;);return e}(o,i)+1).join("")}var G=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return n(t)?t:[t]},V=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},H=function(t,r){try{var e=Object.keys(t);return G(e,r)}catch(t){return!1}},W=function(t){return V("string"==typeof t?t:JSON.stringify(t))},Z=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function X(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var tt=Array.prototype.splice;function rt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},rt.prototype.set=function(t,r){var e=this.__data__,n=X(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function nt(t){if(!et(t))return!1;var r=y(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var ot,it=a["__core-js_shared__"],ut=(ot=/[^.]+$/.exec(it&&it.keys&&it.keys.IE_PROTO||""))?"Symbol(src)_1."+ot:"";var at=Function.prototype.toString;var ft=/^\[object .+?Constructor\]$/,st=Function.prototype,ct=Object.prototype,ht=st.toString,pt=ct.hasOwnProperty,lt=RegExp("^"+ht.call(pt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function gt(t){return!(!et(t)||function(t){return!!ut&&ut in t}(t))&&(nt(t)?lt:ft).test(function(t){if(null!=t){try{return at.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function yt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return gt(e)?e:void 0}var vt=yt(a,"Map"),dt=yt(Object,"create");var _t=Object.prototype.hasOwnProperty;var bt=Object.prototype.hasOwnProperty;function wt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Jt(t.length)&&!nt(t)}var Gt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Qt=Gt&&"object"==typeof module&&module&&!module.nodeType&&module,Vt=Qt&&Qt.exports===Gt?a.Buffer:void 0,Ht=(Vt?Vt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Zt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Kt=Zt&&"object"==typeof module&&module&&!module.nodeType&&module,Xt=Kt&&Kt.exports===Zt&&i.process,tr=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Xt&&Xt.binding&&Xt.binding("util")}catch(t){}}(),rr=tr&&tr.isTypedArray,er=rr?function(t){return function(r){return t(r)}}(rr):function(t){return b(t)&&Jt(t.length)&&!!Wt[y(t)]};function nr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var or=Object.prototype.hasOwnProperty;function ir(t,r,e){var n=t[r];or.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||jt(t,r,e)}var ur=/^(?:0|[1-9]\d*)$/;function ar(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&ur.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(br);function Ar(t,r){return mr(function(t,r,e){return r=_r(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,i=_r(n.length-r,0),u=Array(i);++o1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=Er.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!et(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ar(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e>18&63]+re[o>>12&63]+re[o>>6&63]+re[63&o]);return i.join("")}function ae(t){var r;oe||ie();for(var e=t.length,n=e%3,o="",i=[],u=0,a=e-n;ua?a:u+16383));return 1===n?(r=t[e-1],o+=re[r>>2],o+=re[r<<4&63],o+="=="):2===n&&(r=(t[e-2]<<8)+t[e-1],o+=re[r>>10],o+=re[r>>4&63],o+=re[r<<2&63],o+="="),i.push(o),i.join("")}function fe(t,r,e,n,o){var i,u,a=8*o-n-1,f=(1<>1,c=-7,h=e?o-1:0,p=e?-1:1,l=t[r+h];for(h+=p,i=l&(1<<-c)-1,l>>=-c,c+=a;c>0;i=256*i+t[r+h],h+=p,c-=8);for(u=i&(1<<-c)-1,i>>=-c,c+=n;c>0;u=256*u+t[r+h],h+=p,c-=8);if(0===i)i=1-s;else{if(i===f)return u?NaN:1/0*(l?-1:1);u+=Math.pow(2,n),i-=s}return(l?-1:1)*u*Math.pow(2,i-n)}function se(t,r,e,n,o,i){var u,a,f,s=8*i-o-1,c=(1<>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,l=n?0:i-1,g=n?1:-1,y=r<0||0===r&&1/r<0?1:0;for(r=Math.abs(r),isNaN(r)||r===1/0?(a=isNaN(r)?1:0,u=c):(u=Math.floor(Math.log(r)/Math.LN2),r*(f=Math.pow(2,-u))<1&&(u--,f*=2),(r+=u+h>=1?p/f:p*Math.pow(2,1-h))*f>=2&&(u++,f/=2),u+h>=c?(a=0,u=c):u+h>=1?(a=(r*f-1)*Math.pow(2,o),u+=h):(a=r*Math.pow(2,h-1)*Math.pow(2,o),u=0));o>=8;t[e+l]=255&a,l+=g,a/=256,o-=8);for(u=u<0;t[e+l]=255&u,l+=g,u/=256,s-=8);t[e+l-g]|=128*y}var ce={}.toString,he=Array.isArray||function(t){return"[object Array]"==ce.call(t)};function pe(){return ge.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function le(t,r){if(pe()=pe())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+pe().toString(16)+" bytes");return 0|t}function we(t){return!(null==t||!t._isBuffer)}function me(t,r){if(we(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var e=t.length;if(0===e)return 0;for(var n=!1;;)switch(r){case"ascii":case"latin1":case"binary":return e;case"utf8":case"utf-8":case void 0:return Qe(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*e;case"hex":return e>>>1;case"base64":return Ve(t).length;default:if(n)return Qe(t).length;r=(""+r).toLowerCase(),n=!0}}function Ae(t,r,e){var n=!1;if((void 0===r||r<0)&&(r=0),r>this.length)return"";if((void 0===e||e>this.length)&&(e=this.length),e<=0)return"";if((e>>>=0)<=(r>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return Ye(this,r,e);case"utf8":case"utf-8":return Ne(this,r,e);case"ascii":return Ie(this,r,e);case"latin1":case"binary":return Ce(this,r,e);case"base64":return Be(this,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Me(this,r,e);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function Ee(t,r,e){var n=t[r];t[r]=t[e],t[e]=n}function xe(t,r,e,n,o){if(0===t.length)return-1;if("string"==typeof e?(n=e,e=0):e>2147483647?e=2147483647:e<-2147483648&&(e=-2147483648),e=+e,isNaN(e)&&(e=o?0:t.length-1),e<0&&(e=t.length+e),e>=t.length){if(o)return-1;e=t.length-1}else if(e<0){if(!o)return-1;e=0}if("string"==typeof r&&(r=ge.from(r,n)),we(r))return 0===r.length?-1:je(t,r,e,n,o);if("number"==typeof r)return r&=255,ge.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,r,e):Uint8Array.prototype.lastIndexOf.call(t,r,e):je(t,[r],e,n,o);throw new TypeError("val must be string, number or Buffer")}function je(t,r,e,n,o){var i,u=1,a=t.length,f=r.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||r.length<2)return-1;u=2,a/=2,f/=2,e/=2}function s(t,r){return 1===u?t[r]:t.readUInt16BE(r*u)}if(o){var c=-1;for(i=e;ia&&(e=a-f),i=e;i>=0;i--){for(var h=!0,p=0;po&&(n=o):n=o;var i=r.length;if(i%2!=0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var u=0;u>8,o=e%256,i.push(o),i.push(n);return i}(r,t.length-e),t,e,n)}function Be(t,r,e){return 0===r&&e===t.length?ae(t):ae(t.slice(r,e))}function Ne(t,r,e){e=Math.min(t.length,e);for(var n=[],o=r;o239?4:s>223?3:s>191?2:1;if(o+h<=e)switch(h){case 1:s<128&&(c=s);break;case 2:128==(192&(i=t[o+1]))&&(f=(31&s)<<6|63&i)>127&&(c=f);break;case 3:i=t[o+1],u=t[o+2],128==(192&i)&&128==(192&u)&&(f=(15&s)<<12|(63&i)<<6|63&u)>2047&&(f<55296||f>57343)&&(c=f);break;case 4:i=t[o+1],u=t[o+2],a=t[o+3],128==(192&i)&&128==(192&u)&&128==(192&a)&&(f=(15&s)<<18|(63&i)<<12|(63&u)<<6|63&a)>65535&&f<1114112&&(c=f)}null===c?(c=65533,h=1):c>65535&&(c-=65536,n.push(c>>>10&1023|55296),c=56320|1023&c),n.push(c),o+=h}return function(t){var r=t.length;if(r<=4096)return String.fromCharCode.apply(String,t);var e="",n=0;for(;n0&&(t=this.toString("hex",0,50).match(/.{2}/g).join(" "),this.length>50&&(t+=" ... ")),""},ge.prototype.compare=function(t,r,e,n,o){if(!we(t))throw new TypeError("Argument must be a Buffer");if(void 0===r&&(r=0),void 0===e&&(e=t?t.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),r<0||e>t.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&r>=e)return 0;if(n>=o)return-1;if(r>=e)return 1;if(this===t)return 0;for(var i=(o>>>=0)-(n>>>=0),u=(e>>>=0)-(r>>>=0),a=Math.min(i,u),f=this.slice(n,o),s=t.slice(r,e),c=0;co)&&(e=o),t.length>0&&(e<0||r<0)||r>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return Pe(this,t,r,e);case"utf8":case"utf-8":return Re(this,t,r,e);case"ascii":return Oe(this,t,r,e);case"latin1":case"binary":return Te(this,t,r,e);case"base64":return Se(this,t,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Ue(this,t,r,e);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},ge.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Ie(t,r,e){var n="";e=Math.min(t.length,e);for(var o=r;on)&&(e=n);for(var o="",i=r;ie)throw new RangeError("Trying to access beyond buffer length")}function De(t,r,e,n,o,i){if(!we(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(r>o||rt.length)throw new RangeError("Index out of range")}function Le(t,r,e,n){r<0&&(r=65535+r+1);for(var o=0,i=Math.min(t.length-e,2);o>>8*(n?o:1-o)}function ze(t,r,e,n){r<0&&(r=4294967295+r+1);for(var o=0,i=Math.min(t.length-e,4);o>>8*(n?o:3-o)&255}function Fe(t,r,e,n,o,i){if(e+n>t.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function qe(t,r,e,n,o){return o||Fe(t,0,e,4),se(t,r,e,n,23,4),e+4}function Je(t,r,e,n,o){return o||Fe(t,0,e,8),se(t,r,e,n,52,8),e+8}ge.prototype.slice=function(t,r){var e,n=this.length;if((t=~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),(r=void 0===r?n:~~r)<0?(r+=n)<0&&(r=0):r>n&&(r=n),r0&&(o*=256);)n+=this[t+--r]*o;return n},ge.prototype.readUInt8=function(t,r){return r||ke(t,1,this.length),this[t]},ge.prototype.readUInt16LE=function(t,r){return r||ke(t,2,this.length),this[t]|this[t+1]<<8},ge.prototype.readUInt16BE=function(t,r){return r||ke(t,2,this.length),this[t]<<8|this[t+1]},ge.prototype.readUInt32LE=function(t,r){return r||ke(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},ge.prototype.readUInt32BE=function(t,r){return r||ke(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},ge.prototype.readIntLE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=this[t],o=1,i=0;++i=(o*=128)&&(n-=Math.pow(2,8*r)),n},ge.prototype.readIntBE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=r,o=1,i=this[t+--n];n>0&&(o*=256);)i+=this[t+--n]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*r)),i},ge.prototype.readInt8=function(t,r){return r||ke(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},ge.prototype.readInt16LE=function(t,r){r||ke(t,2,this.length);var e=this[t]|this[t+1]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt16BE=function(t,r){r||ke(t,2,this.length);var e=this[t+1]|this[t]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt32LE=function(t,r){return r||ke(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},ge.prototype.readInt32BE=function(t,r){return r||ke(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},ge.prototype.readFloatLE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!0,23,4)},ge.prototype.readFloatBE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!1,23,4)},ge.prototype.readDoubleLE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!0,52,8)},ge.prototype.readDoubleBE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!1,52,8)},ge.prototype.writeUIntLE=function(t,r,e,n){(t=+t,r|=0,e|=0,n)||De(this,t,r,e,Math.pow(2,8*e)-1,0);var o=1,i=0;for(this[r]=255&t;++i=0&&(i*=256);)this[r+o]=t/i&255;return r+e},ge.prototype.writeUInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,255,0),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[r]=255&t,r+1},ge.prototype.writeUInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeUInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeUInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r+3]=t>>>24,this[r+2]=t>>>16,this[r+1]=t>>>8,this[r]=255&t):ze(this,t,r,!0),r+4},ge.prototype.writeUInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeIntLE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=0,u=1,a=0;for(this[r]=255&t;++i>0)-a&255;return r+e},ge.prototype.writeIntBE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=e-1,u=1,a=0;for(this[r+i]=255&t;--i>=0&&(u*=256);)t<0&&0===a&&0!==this[r+i+1]&&(a=1),this[r+i]=(t/u>>0)-a&255;return r+e},ge.prototype.writeInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,127,-128),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[r]=255&t,r+1},ge.prototype.writeInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8,this[r+2]=t>>>16,this[r+3]=t>>>24):ze(this,t,r,!0),r+4},ge.prototype.writeInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeFloatLE=function(t,r,e){return qe(this,t,r,!0,e)},ge.prototype.writeFloatBE=function(t,r,e){return qe(this,t,r,!1,e)},ge.prototype.writeDoubleLE=function(t,r,e){return Je(this,t,r,!0,e)},ge.prototype.writeDoubleBE=function(t,r,e){return Je(this,t,r,!1,e)},ge.prototype.copy=function(t,r,e,n){if(e||(e=0),n||0===n||(n=this.length),r>=t.length&&(r=t.length),r||(r=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-r=0;--o)t[o+r]=this[o+e];else if(i<1e3||!ge.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,e=void 0===e?this.length:e>>>0,t||(t=0),"number"==typeof t)for(i=r;i55295&&e<57344){if(!o){if(e>56319){(r-=3)>-1&&i.push(239,191,189);continue}if(u+1===n){(r-=3)>-1&&i.push(239,191,189);continue}o=e;continue}if(e<56320){(r-=3)>-1&&i.push(239,191,189),o=e;continue}e=65536+(o-55296<<10|e-56320)}else o&&(r-=3)>-1&&i.push(239,191,189);if(o=null,e<128){if((r-=1)<0)break;i.push(e)}else if(e<2048){if((r-=2)<0)break;i.push(e>>6|192,63&e|128)}else if(e<65536){if((r-=3)<0)break;i.push(e>>12|224,e>>6&63|128,63&e|128)}else{if(!(e<1114112))throw new Error("Invalid code point");if((r-=4)<0)break;i.push(e>>18|240,e>>12&63|128,e>>6&63|128,63&e|128)}}return i}function Ve(t){return function(t){var r,e,n,o,i,u;oe||ie();var a=t.length;if(a%4>0)throw new Error("Invalid string. Length must be a multiple of 4");i="="===t[a-2]?2:"="===t[a-1]?1:0,u=new ne(3*a/4-i),n=i>0?a-4:a;var f=0;for(r=0,e=0;r>16&255,u[f++]=o>>8&255,u[f++]=255&o;return 2===i?(o=ee[t.charCodeAt(r)]<<2|ee[t.charCodeAt(r+1)]>>4,u[f++]=255&o):1===i&&(o=ee[t.charCodeAt(r)]<<10|ee[t.charCodeAt(r+1)]<<4|ee[t.charCodeAt(r+2)]>>2,u[f++]=o>>8&255,u[f++]=255&o),u}(function(t){if((t=function(t){if(t.trim)return t.trim();return t.replace(/^\s+|\s+$/g,"")}(t).replace($e,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function He(t,r,e,n){for(var o=0;o=r.length||o>=t.length);++o)r[o+e]=t[o];return o}function We(t){return null!=t&&(!!t._isBuffer||Ze(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&Ze(t.slice(0,0))}(t))}function Ze(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}var Ke=function(t,r){if(r instanceof Error){var e={};return Object.getOwnPropertyNames(r).forEach((function(t){e[t]=r[t]})),e}return r};var Xe=function(t,r){try{var e=t.headers.accept.split(",");return r?e.filter((function(t){return t===r})):e}catch(t){return[]}},tn=function(t,r){return!!Xe(t,r).length},rn=function(t,r){return t.path===r.jsonqlPath};exports.VERSION="1.2.0",exports.buff=function(t,r){return void 0===r&&(r="base64"),We(t)?t:new ge.from(t,r)},exports.cacheBurst=Yr,exports.cacheBurstUrl=function(t){return Cr(t,Yr())},exports.chainFns=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},exports.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):xr(t,e)}))}))}),Promise.resolve(!1===r?[]:j(r)?r:{}))},exports.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("acknowledge_reply",t,r,e)},exports.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},exports.createMutation=Jr,exports.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Jr(t,r,e,n))},exports.createQuery=qr,exports.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},exports.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("emit_reply",t,r,e)},exports.createWsReply=Xr,exports.dasherize=Ir,exports.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ur("Unknown "+r+" to extract argument from!")}},exports.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Tr(e,r);return n}catch(t){throw new Tr(e,t)}},exports.extractSocketPart=Br,exports.extractWsPayload=function(t,r){void 0===r&&(r=Z);try{var e,n=W(t);if(!1!==(e=te(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ur("payload can not decoded",t)}catch(t){return r("error",t)}},exports.findFromContract=function(t,e,n){return!!(n[t]&&n[t][e]&&n[t][e].file&&r.existsSync(n[t][e].file))&&n[t][e].file},exports.formatPayload=Lr,exports.getCallMethod=function(t){switch(!0){case t===Rr[0]:return"query";case t===Rr[1]:return"mutation";default:return!1}},exports.getConfigValue=function(t,r){return r&&j(r)&&t in r?r[t]:void 0},exports.getDocLen=function(t){return ge.byteLength(t,"utf8")},exports.getMutationFromArgs=Qr,exports.getMutationFromPayload=function(t){var r=Gr(t,Qr);if(!1!==r)return r;throw new Sr("[getMutationArgs] Payload is malformed!",t)},exports.getNamespace=Wr,exports.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},exports.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Wr(t),o=e?Hr(r):function(t,r){var e,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},exports.getPathToFn=function(t,n,o){var i=o.resolverDir,u=Ir(t),a=[];o.contract&&o.contract[n]&&o.contract[n].path&&a.push(o.contract[n].path),a.push(e.join(i,n,u,[Or,Pr].join("."))),a.push(e.join(i,n,[u,Pr].join(".")));for(var f=a.length,s=0;s=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var i=Array(o);++n-1;);return e}(o,i),function(t,r){for(var e=t.length;e--&&U(r,t[e],0)>-1;);return e}(o,i)+1).join("")}var G=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return n(t)?t:[t]},V=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},H=function(t,r){try{var e=Object.keys(t);return G(e,r)}catch(t){return!1}},W=function(t){return V("string"==typeof t?t:JSON.stringify(t))},Z=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function X(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var tt=Array.prototype.splice;function rt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},rt.prototype.set=function(t,r){var e=this.__data__,n=X(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function nt(t){if(!et(t))return!1;var r=y(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var ot,it=a["__core-js_shared__"],ut=(ot=/[^.]+$/.exec(it&&it.keys&&it.keys.IE_PROTO||""))?"Symbol(src)_1."+ot:"";var at=Function.prototype.toString;var ft=/^\[object .+?Constructor\]$/,st=Function.prototype,ct=Object.prototype,ht=st.toString,pt=ct.hasOwnProperty,lt=RegExp("^"+ht.call(pt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function gt(t){return!(!et(t)||function(t){return!!ut&&ut in t}(t))&&(nt(t)?lt:ft).test(function(t){if(null!=t){try{return at.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function yt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return gt(e)?e:void 0}var vt=yt(a,"Map"),dt=yt(Object,"create");var _t=Object.prototype.hasOwnProperty;var bt=Object.prototype.hasOwnProperty;function wt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Jt(t.length)&&!nt(t)}var Gt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Qt=Gt&&"object"==typeof module&&module&&!module.nodeType&&module,Vt=Qt&&Qt.exports===Gt?a.Buffer:void 0,Ht=(Vt?Vt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Zt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Kt=Zt&&"object"==typeof module&&module&&!module.nodeType&&module,Xt=Kt&&Kt.exports===Zt&&i.process,tr=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Xt&&Xt.binding&&Xt.binding("util")}catch(t){}}(),rr=tr&&tr.isTypedArray,er=rr?function(t){return function(r){return t(r)}}(rr):function(t){return b(t)&&Jt(t.length)&&!!Wt[y(t)]};function nr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var or=Object.prototype.hasOwnProperty;function ir(t,r,e){var n=t[r];or.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||jt(t,r,e)}var ur=/^(?:0|[1-9]\d*)$/;function ar(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&ur.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(br);function Ar(t,r){return mr(function(t,r,e){return r=_r(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,i=_r(n.length-r,0),u=Array(i);++o1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=Er.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!et(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ar(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e>18&63]+re[o>>12&63]+re[o>>6&63]+re[63&o]);return i.join("")}function ae(t){var r;oe||ie();for(var e=t.length,n=e%3,o="",i=[],u=0,a=e-n;ua?a:u+16383));return 1===n?(r=t[e-1],o+=re[r>>2],o+=re[r<<4&63],o+="=="):2===n&&(r=(t[e-2]<<8)+t[e-1],o+=re[r>>10],o+=re[r>>4&63],o+=re[r<<2&63],o+="="),i.push(o),i.join("")}function fe(t,r,e,n,o){var i,u,a=8*o-n-1,f=(1<>1,c=-7,h=e?o-1:0,p=e?-1:1,l=t[r+h];for(h+=p,i=l&(1<<-c)-1,l>>=-c,c+=a;c>0;i=256*i+t[r+h],h+=p,c-=8);for(u=i&(1<<-c)-1,i>>=-c,c+=n;c>0;u=256*u+t[r+h],h+=p,c-=8);if(0===i)i=1-s;else{if(i===f)return u?NaN:1/0*(l?-1:1);u+=Math.pow(2,n),i-=s}return(l?-1:1)*u*Math.pow(2,i-n)}function se(t,r,e,n,o,i){var u,a,f,s=8*i-o-1,c=(1<>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,l=n?0:i-1,g=n?1:-1,y=r<0||0===r&&1/r<0?1:0;for(r=Math.abs(r),isNaN(r)||r===1/0?(a=isNaN(r)?1:0,u=c):(u=Math.floor(Math.log(r)/Math.LN2),r*(f=Math.pow(2,-u))<1&&(u--,f*=2),(r+=u+h>=1?p/f:p*Math.pow(2,1-h))*f>=2&&(u++,f/=2),u+h>=c?(a=0,u=c):u+h>=1?(a=(r*f-1)*Math.pow(2,o),u+=h):(a=r*Math.pow(2,h-1)*Math.pow(2,o),u=0));o>=8;t[e+l]=255&a,l+=g,a/=256,o-=8);for(u=u<0;t[e+l]=255&u,l+=g,u/=256,s-=8);t[e+l-g]|=128*y}var ce={}.toString,he=Array.isArray||function(t){return"[object Array]"==ce.call(t)};function pe(){return ge.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function le(t,r){if(pe()=pe())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+pe().toString(16)+" bytes");return 0|t}function we(t){return!(null==t||!t._isBuffer)}function me(t,r){if(we(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var e=t.length;if(0===e)return 0;for(var n=!1;;)switch(r){case"ascii":case"latin1":case"binary":return e;case"utf8":case"utf-8":case void 0:return Qe(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*e;case"hex":return e>>>1;case"base64":return Ve(t).length;default:if(n)return Qe(t).length;r=(""+r).toLowerCase(),n=!0}}function Ae(t,r,e){var n=!1;if((void 0===r||r<0)&&(r=0),r>this.length)return"";if((void 0===e||e>this.length)&&(e=this.length),e<=0)return"";if((e>>>=0)<=(r>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return Ye(this,r,e);case"utf8":case"utf-8":return Ne(this,r,e);case"ascii":return Ie(this,r,e);case"latin1":case"binary":return Ce(this,r,e);case"base64":return Be(this,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Me(this,r,e);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function Ee(t,r,e){var n=t[r];t[r]=t[e],t[e]=n}function xe(t,r,e,n,o){if(0===t.length)return-1;if("string"==typeof e?(n=e,e=0):e>2147483647?e=2147483647:e<-2147483648&&(e=-2147483648),e=+e,isNaN(e)&&(e=o?0:t.length-1),e<0&&(e=t.length+e),e>=t.length){if(o)return-1;e=t.length-1}else if(e<0){if(!o)return-1;e=0}if("string"==typeof r&&(r=ge.from(r,n)),we(r))return 0===r.length?-1:je(t,r,e,n,o);if("number"==typeof r)return r&=255,ge.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,r,e):Uint8Array.prototype.lastIndexOf.call(t,r,e):je(t,[r],e,n,o);throw new TypeError("val must be string, number or Buffer")}function je(t,r,e,n,o){var i,u=1,a=t.length,f=r.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||r.length<2)return-1;u=2,a/=2,f/=2,e/=2}function s(t,r){return 1===u?t[r]:t.readUInt16BE(r*u)}if(o){var c=-1;for(i=e;ia&&(e=a-f),i=e;i>=0;i--){for(var h=!0,p=0;po&&(n=o):n=o;var i=r.length;if(i%2!=0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var u=0;u>8,o=e%256,i.push(o),i.push(n);return i}(r,t.length-e),t,e,n)}function Be(t,r,e){return 0===r&&e===t.length?ae(t):ae(t.slice(r,e))}function Ne(t,r,e){e=Math.min(t.length,e);for(var n=[],o=r;o239?4:s>223?3:s>191?2:1;if(o+h<=e)switch(h){case 1:s<128&&(c=s);break;case 2:128==(192&(i=t[o+1]))&&(f=(31&s)<<6|63&i)>127&&(c=f);break;case 3:i=t[o+1],u=t[o+2],128==(192&i)&&128==(192&u)&&(f=(15&s)<<12|(63&i)<<6|63&u)>2047&&(f<55296||f>57343)&&(c=f);break;case 4:i=t[o+1],u=t[o+2],a=t[o+3],128==(192&i)&&128==(192&u)&&128==(192&a)&&(f=(15&s)<<18|(63&i)<<12|(63&u)<<6|63&a)>65535&&f<1114112&&(c=f)}null===c?(c=65533,h=1):c>65535&&(c-=65536,n.push(c>>>10&1023|55296),c=56320|1023&c),n.push(c),o+=h}return function(t){var r=t.length;if(r<=4096)return String.fromCharCode.apply(String,t);var e="",n=0;for(;n0&&(t=this.toString("hex",0,50).match(/.{2}/g).join(" "),this.length>50&&(t+=" ... ")),""},ge.prototype.compare=function(t,r,e,n,o){if(!we(t))throw new TypeError("Argument must be a Buffer");if(void 0===r&&(r=0),void 0===e&&(e=t?t.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),r<0||e>t.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&r>=e)return 0;if(n>=o)return-1;if(r>=e)return 1;if(this===t)return 0;for(var i=(o>>>=0)-(n>>>=0),u=(e>>>=0)-(r>>>=0),a=Math.min(i,u),f=this.slice(n,o),s=t.slice(r,e),c=0;co)&&(e=o),t.length>0&&(e<0||r<0)||r>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return Pe(this,t,r,e);case"utf8":case"utf-8":return Re(this,t,r,e);case"ascii":return Oe(this,t,r,e);case"latin1":case"binary":return Te(this,t,r,e);case"base64":return Se(this,t,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Ue(this,t,r,e);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},ge.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Ie(t,r,e){var n="";e=Math.min(t.length,e);for(var o=r;on)&&(e=n);for(var o="",i=r;ie)throw new RangeError("Trying to access beyond buffer length")}function De(t,r,e,n,o,i){if(!we(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(r>o||rt.length)throw new RangeError("Index out of range")}function Le(t,r,e,n){r<0&&(r=65535+r+1);for(var o=0,i=Math.min(t.length-e,2);o>>8*(n?o:1-o)}function ze(t,r,e,n){r<0&&(r=4294967295+r+1);for(var o=0,i=Math.min(t.length-e,4);o>>8*(n?o:3-o)&255}function Fe(t,r,e,n,o,i){if(e+n>t.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function qe(t,r,e,n,o){return o||Fe(t,0,e,4),se(t,r,e,n,23,4),e+4}function Je(t,r,e,n,o){return o||Fe(t,0,e,8),se(t,r,e,n,52,8),e+8}ge.prototype.slice=function(t,r){var e,n=this.length;if((t=~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),(r=void 0===r?n:~~r)<0?(r+=n)<0&&(r=0):r>n&&(r=n),r0&&(o*=256);)n+=this[t+--r]*o;return n},ge.prototype.readUInt8=function(t,r){return r||ke(t,1,this.length),this[t]},ge.prototype.readUInt16LE=function(t,r){return r||ke(t,2,this.length),this[t]|this[t+1]<<8},ge.prototype.readUInt16BE=function(t,r){return r||ke(t,2,this.length),this[t]<<8|this[t+1]},ge.prototype.readUInt32LE=function(t,r){return r||ke(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},ge.prototype.readUInt32BE=function(t,r){return r||ke(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},ge.prototype.readIntLE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=this[t],o=1,i=0;++i=(o*=128)&&(n-=Math.pow(2,8*r)),n},ge.prototype.readIntBE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=r,o=1,i=this[t+--n];n>0&&(o*=256);)i+=this[t+--n]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*r)),i},ge.prototype.readInt8=function(t,r){return r||ke(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},ge.prototype.readInt16LE=function(t,r){r||ke(t,2,this.length);var e=this[t]|this[t+1]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt16BE=function(t,r){r||ke(t,2,this.length);var e=this[t+1]|this[t]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt32LE=function(t,r){return r||ke(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},ge.prototype.readInt32BE=function(t,r){return r||ke(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},ge.prototype.readFloatLE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!0,23,4)},ge.prototype.readFloatBE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!1,23,4)},ge.prototype.readDoubleLE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!0,52,8)},ge.prototype.readDoubleBE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!1,52,8)},ge.prototype.writeUIntLE=function(t,r,e,n){(t=+t,r|=0,e|=0,n)||De(this,t,r,e,Math.pow(2,8*e)-1,0);var o=1,i=0;for(this[r]=255&t;++i=0&&(i*=256);)this[r+o]=t/i&255;return r+e},ge.prototype.writeUInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,255,0),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[r]=255&t,r+1},ge.prototype.writeUInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeUInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeUInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r+3]=t>>>24,this[r+2]=t>>>16,this[r+1]=t>>>8,this[r]=255&t):ze(this,t,r,!0),r+4},ge.prototype.writeUInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeIntLE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=0,u=1,a=0;for(this[r]=255&t;++i>0)-a&255;return r+e},ge.prototype.writeIntBE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=e-1,u=1,a=0;for(this[r+i]=255&t;--i>=0&&(u*=256);)t<0&&0===a&&0!==this[r+i+1]&&(a=1),this[r+i]=(t/u>>0)-a&255;return r+e},ge.prototype.writeInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,127,-128),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[r]=255&t,r+1},ge.prototype.writeInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8,this[r+2]=t>>>16,this[r+3]=t>>>24):ze(this,t,r,!0),r+4},ge.prototype.writeInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeFloatLE=function(t,r,e){return qe(this,t,r,!0,e)},ge.prototype.writeFloatBE=function(t,r,e){return qe(this,t,r,!1,e)},ge.prototype.writeDoubleLE=function(t,r,e){return Je(this,t,r,!0,e)},ge.prototype.writeDoubleBE=function(t,r,e){return Je(this,t,r,!1,e)},ge.prototype.copy=function(t,r,e,n){if(e||(e=0),n||0===n||(n=this.length),r>=t.length&&(r=t.length),r||(r=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-r=0;--o)t[o+r]=this[o+e];else if(i<1e3||!ge.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,e=void 0===e?this.length:e>>>0,t||(t=0),"number"==typeof t)for(i=r;i55295&&e<57344){if(!o){if(e>56319){(r-=3)>-1&&i.push(239,191,189);continue}if(u+1===n){(r-=3)>-1&&i.push(239,191,189);continue}o=e;continue}if(e<56320){(r-=3)>-1&&i.push(239,191,189),o=e;continue}e=65536+(o-55296<<10|e-56320)}else o&&(r-=3)>-1&&i.push(239,191,189);if(o=null,e<128){if((r-=1)<0)break;i.push(e)}else if(e<2048){if((r-=2)<0)break;i.push(e>>6|192,63&e|128)}else if(e<65536){if((r-=3)<0)break;i.push(e>>12|224,e>>6&63|128,63&e|128)}else{if(!(e<1114112))throw new Error("Invalid code point");if((r-=4)<0)break;i.push(e>>18|240,e>>12&63|128,e>>6&63|128,63&e|128)}}return i}function Ve(t){return function(t){var r,e,n,o,i,u;oe||ie();var a=t.length;if(a%4>0)throw new Error("Invalid string. Length must be a multiple of 4");i="="===t[a-2]?2:"="===t[a-1]?1:0,u=new ne(3*a/4-i),n=i>0?a-4:a;var f=0;for(r=0,e=0;r>16&255,u[f++]=o>>8&255,u[f++]=255&o;return 2===i?(o=ee[t.charCodeAt(r)]<<2|ee[t.charCodeAt(r+1)]>>4,u[f++]=255&o):1===i&&(o=ee[t.charCodeAt(r)]<<10|ee[t.charCodeAt(r+1)]<<4|ee[t.charCodeAt(r+2)]>>2,u[f++]=o>>8&255,u[f++]=255&o),u}(function(t){if((t=function(t){if(t.trim)return t.trim();return t.replace(/^\s+|\s+$/g,"")}(t).replace($e,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function He(t,r,e,n){for(var o=0;o=r.length||o>=t.length);++o)r[o+e]=t[o];return o}function We(t){return null!=t&&(!!t._isBuffer||Ze(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&Ze(t.slice(0,0))}(t))}function Ze(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}var Ke=function(t,r){if(r instanceof Error){var e={};return Object.getOwnPropertyNames(r).forEach((function(t){e[t]=r[t]})),e}return r};var Xe=function(t,r){try{var e=t.headers.accept.split(",");return r?e.filter((function(t){return t===r})):e}catch(t){return[]}},tn=function(t,r){return!!Xe(t,r).length},rn=function(t,r){return t.path===r.jsonqlPath};exports.VERSION="1.2.1",exports.buff=function(t,r){return void 0===r&&(r="base64"),We(t)?t:new ge.from(t,r)},exports.cacheBurst=Yr,exports.cacheBurstUrl=function(t){return Cr(t,Yr())},exports.chainFns=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},exports.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):xr(t,e)}))}))}),Promise.resolve(!1===r?[]:j(r)?r:{}))},exports.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("acknowledge_reply",t,r,e)},exports.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},exports.createMutation=Jr,exports.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Jr(t,r,e,n))},exports.createQuery=qr,exports.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},exports.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("emit_reply",t,r,e)},exports.createWsReply=Xr,exports.dasherize=Ir,exports.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ur("Unknown "+r+" to extract argument from!")}},exports.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Tr(e,r);return n}catch(t){throw new Tr(e,t)}},exports.extractSocketPart=Br,exports.extractWsPayload=function(t,r){void 0===r&&(r=Z);try{var e,n=W(t);if(!1!==(e=te(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ur("payload can not decoded",t)}catch(t){return r("error",t)}},exports.findFromContract=function(t,e,n){return!!(n[t]&&n[t][e]&&n[t][e].file&&r.existsSync(n[t][e].file))&&n[t][e].file},exports.formatPayload=Lr,exports.getCallMethod=function(t){switch(!0){case t===Rr[0]:return"query";case t===Rr[1]:return"mutation";default:return!1}},exports.getConfigValue=function(t,r){return r&&j(r)&&t in r?r[t]:void 0},exports.getDocLen=function(t){return ge.byteLength(t,"utf8")},exports.getMutationFromArgs=Qr,exports.getMutationFromPayload=function(t){var r=Gr(t,Qr);if(!1!==r)return r;throw new Sr("[getMutationArgs] Payload is malformed!",t)},exports.getNamespace=Wr,exports.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},exports.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Wr(t),o=e?Hr(r):function(t,r){var e,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},exports.getPathToFn=function(t,n,o){var i=o.resolverDir,u=Ir(t),a=[];o.contract&&o.contract[n]&&o.contract[n].path&&a.push(o.contract[n].path),a.push(e.join(i,n,u,[Or,Pr].join("."))),a.push(e.join(i,n,[u,Pr].join(".")));for(var f=a.length,s=0;s Date: Tue, 17 Mar 2020 07:57:28 +0800 Subject: [PATCH 11/66] update deps --- packages/ws-client-core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json index 6baeebd0..009e1786 100644 --- a/packages/ws-client-core/package.json +++ b/packages/ws-client-core/package.json @@ -58,7 +58,7 @@ "jsonql-constants": "^2.0.4", "jsonql-errors": "^1.2.1", "jsonql-params-validator": "^1.6.1", - "jsonql-utils": "^1.2.0" + "jsonql-utils": "^1.2.1" }, "devDependencies": { "ava": "^3.5.0", -- Gitee From 8eb657e667c14c8ff640dcf9e38a208c0b00b871 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 08:05:06 +0800 Subject: [PATCH 12/66] Check url is correct now need to check the server side --- packages/@jsonql/ws/main.js | 28 +++++++++++-------- packages/@jsonql/ws/main.js.map | 2 +- .../bind-framework-to-jsonql.js | 8 +++--- .../init-websocket-client.js | 12 +++++--- .../src/share/create-nsp-clients.js | 1 + 5 files changed, 30 insertions(+), 21 deletions(-) diff --git a/packages/@jsonql/ws/main.js b/packages/@jsonql/ws/main.js index cd77b7fa..3c5dba5f 100644 --- a/packages/@jsonql/ws/main.js +++ b/packages/@jsonql/ws/main.js @@ -6958,13 +6958,14 @@ function getNamespace(config) { // the public come first @1.0.1 we use the constants instead of the user supplied value // @1.0.4 we use the config value again, because we could control this via the post init return [ - [ base , config.publicNamespace ].join('/'), - [ base , config.privateNamespace ].join('/') + [ base , config.privateNamespace ].join('/'), + [ base , config.publicNamespace ].join('/') ] } return [ base ] } + /** * Got a problem with a contract that is public only the groupByNamespace is wrong * which is actually not a problem when using a fallback, but to be sure things in order @@ -7772,6 +7773,7 @@ function createNspAuthClient(namespace, opts) { var nspAuthClient = opts.nspAuthClient; var log = opts.log; var url = namespace ? [hostname, namespace].join('/') : wssPath; + log("createNspAuthClient -->", url); if (token && typeof token !== 'string') { @@ -8101,9 +8103,7 @@ function initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) { * @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 */ -function initWebSocketClient(WebSocket, auth) { - if ( auth === void 0 ) auth = false; - +function initWebSocketClient(WebSocket, auth, log) { if (auth === false) { /** * Create a non-protected client @@ -8114,9 +8114,11 @@ function initWebSocketClient(WebSocket, auth) { return function createWsClient(url, wsOptions) { if ( wsOptions === void 0 ) wsOptions = {}; - - return new Promise(function (resolver, rejecter) { - var _url = fixWss(url); + var _url = fixWss(url); + log(("nspClient: \n" + _url + "\n"), wsOptions); + + return new Promise(function (resolver, rejecter) { + var unconfirmClient = new WebSocket(_url, wsOptions); initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions); }) @@ -8137,6 +8139,8 @@ function initWebSocketClient(WebSocket, auth) { // console.log('what happen here?', url, ws_url, token) var _url = token && typeof token === 'string' ? (ws_url + "?" + TOKEN_PARAM_NAME + "=" + token) : ws_url; + log(("nspAuthClient: \n" + _url + "\n"), wsOptions); + return new Promise(function (resolver, rejecter) { var unconfirmClient = new WebSocket(_url, wsOptions); initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions); @@ -10832,11 +10836,11 @@ function bindFrameworkToJsonql(frameworkModule) { * @return {object} passing the same 3 input out with additional in the opts */ return function createClientBindingAction(opts, nspMap, ee) { - - opts[NSP_CLIENT] = initWebSocketClient(frameworkModule); - opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true); - // @1.0.7 remove later once everything fixed var log = opts.log; + opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log); + opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log); + // @1.0.7 remove later once everything fixed + log("bindFrameworkToJsonql", ee.name, nspMap); // console.log(`contract`, opts.contract) return createNsp(opts, nspMap, ee) diff --git a/packages/@jsonql/ws/main.js.map b/packages/@jsonql/ws/main.js.map index 2865fb13..14efc2ec 100644 --- a/packages/@jsonql/ws/main.js.map +++ b/packages/@jsonql/ws/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","sources":["node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/lodash-es/_arrayMap.js","../../ws-client-core/node_modules/lodash-es/isArray.js","../../ws-client-core/node_modules/lodash-es/_objectToString.js","../../ws-client-core/node_modules/lodash-es/isObjectLike.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-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/lodash-es/_overArg.js","../../ws-client-core/node_modules/jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/jsonql-params-validator/src/validator.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/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-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-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/node_modules/jsonql-utils/src/generic.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/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-send-method.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/setup-intercom.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/share/create-nsp-clients.js","../../ws-client-core/src/share/trigger-namespaces-on-error.js","../../ws-client-core/src/share/client-event-handler.js","../../ws-client-core/src/share/intercom-methods.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.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/login-event-handler.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/create-nsp/bind-socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.js","src/node-ws-client.js"],"sourcesContent":["export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * 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","// 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","/**\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","// 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","// 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","// 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","/**\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","/** 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","// 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","// 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","// 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// generic placeholder function\nexport const nil = () => false\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.publicNamespace ].join('/'),\n [ base , config.privateNamespace ].join('/')\n ]\n }\n return [ base ]\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/**\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","// 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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log))\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/**\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 createNamespaceErrorHandler(client, opts, ee, nspGroup) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the clientitself\n objDefineProps(client, ON_ERROR_FN_NAME, 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 opts,\n ee\n ]\n}\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 createOnReadyHandler(client, opts, ee) {\n return [\n objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n} from './resolver-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 generator(opts, nspMap, ee) {\n\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n ]\n if (opts.enableAuth) {\n args.push(\n createAuthMethods\n )\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n args.push(setupFinalStep)\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n\n return fn(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 { generator } from './core'\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} frameworkSocketEngine \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(frameworkSocketEngine, config) {\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`jsonql-ws-core-client init error`, err)\n })\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} frameworkSocketEngine 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(frameworkSocketEngine, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(opts => wsClientCoreAction(frameworkSocketEngine, opts))\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 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}","// 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\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, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event handler 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 */\nconst notLoginWsHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n log('[notLoginHandler] 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 handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nconst getPrivateNamespace = (namespaces) => (\n namespaces.length > 1 ? namespaces[0] : false\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 */\nconst logoutEvtHandler = (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(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() {\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 handler\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the handler 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 notLoginWsHandler(privateNamespace, ee, opts)\n })\n}\n\n/**\n * A Event handler 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 */\nconst disconnectedHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedHandlerCallback(resolverName, args) {\n log(`[disconnectedHandler] 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 handler, 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 handler, 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 */\nconst disconnectHandler = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() {\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 disconnectedHandler(namespace, ee, opts)\n })\n })\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts \n * @param {object} ee Event Emitter instance\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 clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) {\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 let isPrivate = false\n let hasPrivate = false\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run in order here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace\n if (!hasPrivate) {\n hasPrivate = isPrivate\n }\n // log(namespace, ' --> nsps --> ', nsps[namespace])\n if (nsps[namespace]) {\n\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n Reflect.apply(bindSocketEventHandler, null, args)\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 notLoginWsHandler(namespace, ee, opts)\n }\n })\n // logout event handler \n if (hasPrivate) {\n log(`Has private and add logoutEvtHandler`)\n logoutEvtHandler(nsps, namespaces, ee, opts)\n }\n // finally the disconnect event handlers\n disconnectHandler(nsps, namespaces, ee, opts) \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 * 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 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 json = toJson(payload)\n const result = extractWsPayload(json)\n if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\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 createInitPing, \n extractPingResult, \n createIntercomPayload \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 // terminate the client \n ws.terminate()\n // return the new one with csrf header\n resolver(new WebSocket(url, Object.assign(wsOptions, header)))\n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\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 = false) {\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 \n return new Promise((resolver, rejecter) => {\n const _url = fixWss(url)\n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\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\n return new Promise((resolver, rejecter) => {\n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\n }\n}\n\nexport { initWebSocketClient }","/** 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","// @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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError,\n createIntercomPayload\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nconst logoutEventHandler = (ee, ws) => {\n // @TODO we need find a way to get the userdata \n ws.send(createIntercomPayload(LOGOUT_EVENT_NAME))\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() {\n try {\n log('terminate ws connection')\n ws.terminate()\n } catch(e) {\n console.error('ws.terminate error', e)\n }\n })\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\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventHandler(ee, ws)\n }\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventHandler } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // arguments for clientEventHandler\n const args = [opts, nspMap, ee, bindSocketEventHandler]\n // now create the nsps\n // const { namespaces } = nspMap\n const { token } = opts\n\n return createNspAction(opts, nspMap, token)\n .then(nsps => {\n args.push(nsps)\n Reflect.apply(clientEventHandler, null, args)\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n }) \n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\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 * @return {object} passing the same 3 input out with additional in the opts\n */\n return function createClientBindingAction(opts, nspMap, ee) {\n\n opts[NSP_CLIENT] = initWebSocketClient(frameworkModule)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true) \n // @1.0.7 remove later once everything fixed \n const { log } = opts\n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ No newline at end of file +{"version":3,"file":"main.js","sources":["node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/lodash-es/_arrayMap.js","../../ws-client-core/node_modules/lodash-es/isArray.js","../../ws-client-core/node_modules/lodash-es/_objectToString.js","../../ws-client-core/node_modules/lodash-es/isObjectLike.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-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/lodash-es/_overArg.js","../../ws-client-core/node_modules/jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/jsonql-params-validator/src/validator.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/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-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-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/node_modules/jsonql-utils/src/generic.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/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-send-method.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/setup-intercom.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/share/create-nsp-clients.js","../../ws-client-core/src/share/trigger-namespaces-on-error.js","../../ws-client-core/src/share/client-event-handler.js","../../ws-client-core/src/share/intercom-methods.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.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/login-event-handler.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/create-nsp/bind-socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.js","src/node-ws-client.js"],"sourcesContent":["export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * 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","// 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","/**\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","// 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","// 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","// 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","/**\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","/** 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","// 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","// 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","// 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// generic placeholder function\nexport const nil = () => false\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/**\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","// 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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log))\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/**\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 createNamespaceErrorHandler(client, opts, ee, nspGroup) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the clientitself\n objDefineProps(client, ON_ERROR_FN_NAME, 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 opts,\n ee\n ]\n}\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 createOnReadyHandler(client, opts, ee) {\n return [\n objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n} from './resolver-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 generator(opts, nspMap, ee) {\n\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n ]\n if (opts.enableAuth) {\n args.push(\n createAuthMethods\n )\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n args.push(setupFinalStep)\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n\n return fn(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 { generator } from './core'\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} frameworkSocketEngine \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(frameworkSocketEngine, config) {\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`jsonql-ws-core-client init error`, err)\n })\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} frameworkSocketEngine 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(frameworkSocketEngine, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(opts => wsClientCoreAction(frameworkSocketEngine, opts))\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}","// 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\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, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event handler 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 */\nconst notLoginWsHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n log('[notLoginHandler] 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 handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nconst getPrivateNamespace = (namespaces) => (\n namespaces.length > 1 ? namespaces[0] : false\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 */\nconst logoutEvtHandler = (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(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() {\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 handler\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the handler 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 notLoginWsHandler(privateNamespace, ee, opts)\n })\n}\n\n/**\n * A Event handler 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 */\nconst disconnectedHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedHandlerCallback(resolverName, args) {\n log(`[disconnectedHandler] 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 handler, 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 handler, 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 */\nconst disconnectHandler = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() {\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 disconnectedHandler(namespace, ee, opts)\n })\n })\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts \n * @param {object} ee Event Emitter instance\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 clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) {\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 let isPrivate = false\n let hasPrivate = false\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run in order here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace\n if (!hasPrivate) {\n hasPrivate = isPrivate\n }\n // log(namespace, ' --> nsps --> ', nsps[namespace])\n if (nsps[namespace]) {\n\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n Reflect.apply(bindSocketEventHandler, null, args)\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 notLoginWsHandler(namespace, ee, opts)\n }\n })\n // logout event handler \n if (hasPrivate) {\n log(`Has private and add logoutEvtHandler`)\n logoutEvtHandler(nsps, namespaces, ee, opts)\n }\n // finally the disconnect event handlers\n disconnectHandler(nsps, namespaces, ee, opts) \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 * 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 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 json = toJson(payload)\n const result = extractWsPayload(json)\n if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\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 createInitPing, \n extractPingResult, \n createIntercomPayload \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 // terminate the client \n ws.terminate()\n // return the new one with csrf header\n resolver(new WebSocket(url, Object.assign(wsOptions, header)))\n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\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 new Promise((resolver, rejecter) => { \n \n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\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\n log(`nspAuthClient: \\n${_url}\\n`, wsOptions)\n\n return new Promise((resolver, rejecter) => {\n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\n }\n}\n\nexport { initWebSocketClient }","/** 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","// @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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError,\n createIntercomPayload\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nconst logoutEventHandler = (ee, ws) => {\n // @TODO we need find a way to get the userdata \n ws.send(createIntercomPayload(LOGOUT_EVENT_NAME))\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() {\n try {\n log('terminate ws connection')\n ws.terminate()\n } catch(e) {\n console.error('ws.terminate error', e)\n }\n })\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\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventHandler(ee, ws)\n }\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventHandler } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // arguments for clientEventHandler\n const args = [opts, nspMap, ee, bindSocketEventHandler]\n // now create the nsps\n // const { namespaces } = nspMap\n const { token } = opts\n\n return createNspAction(opts, nspMap, token)\n .then(nsps => {\n args.push(nsps)\n Reflect.apply(clientEventHandler, null, args)\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n }) \n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\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 * @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 opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log) \n // @1.0.7 remove later once everything fixed \n \n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ No newline at end of file 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-framework-to-jsonql.js index 1d8880c5..cdb6df39 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-framework-to-jsonql.js @@ -17,11 +17,11 @@ function bindFrameworkToJsonql(frameworkModule) { * @return {object} passing the same 3 input out with additional in the opts */ return function createClientBindingAction(opts, nspMap, ee) { - - opts[NSP_CLIENT] = initWebSocketClient(frameworkModule) - opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true) - // @1.0.7 remove later once everything fixed const { log } = opts + opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log) + opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log) + // @1.0.7 remove later once everything fixed + log(`bindFrameworkToJsonql`, ee.name, nspMap) // console.log(`contract`, opts.contract) return createNsp(opts, nspMap, ee) 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 72f83dd9..f91a6b8c 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 @@ -49,7 +49,7 @@ function initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) { * @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 */ -function initWebSocketClient(WebSocket, auth = false) { +function initWebSocketClient(WebSocket, auth, log) { if (auth === false) { /** * Create a non-protected client @@ -58,9 +58,11 @@ function initWebSocketClient(WebSocket, auth = false) { * @return {promise} resolve to the confirmed client */ return function createWsClient(url, wsOptions = {}) { - - return new Promise((resolver, rejecter) => { - const _url = fixWss(url) + const _url = fixWss(url) + log(`nspClient: \n${_url}\n`, wsOptions) + + return new Promise((resolver, rejecter) => { + const unconfirmClient = new WebSocket(_url, wsOptions) initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) }) @@ -79,6 +81,8 @@ function initWebSocketClient(WebSocket, auth = false) { // console.log('what happen here?', url, ws_url, token) const _url = token && typeof token === 'string' ? `${ws_url}?${TOKEN_PARAM_NAME}=${token}` : ws_url + log(`nspAuthClient: \n${_url}\n`, wsOptions) + return new Promise((resolver, rejecter) => { const unconfirmClient = new WebSocket(_url, wsOptions) initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) diff --git a/packages/ws-client-core/src/share/create-nsp-clients.js b/packages/ws-client-core/src/share/create-nsp-clients.js index 330ab258..4347eb6a 100644 --- a/packages/ws-client-core/src/share/create-nsp-clients.js +++ b/packages/ws-client-core/src/share/create-nsp-clients.js @@ -24,6 +24,7 @@ function createNspClient(namespace, opts) { function createNspAuthClient(namespace, opts) { const { hostname, wssPath, token, wsOptions, nspAuthClient, log } = opts const url = namespace ? [hostname, namespace].join('/') : wssPath + log(`createNspAuthClient -->`, url) if (token && typeof token !== 'string') { -- Gitee From a6668444da267c23c5930db8ab28032846c3a38d Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 09:19:13 +0800 Subject: [PATCH 13/66] port intercom-methods over the ws-server and change the client interface for debugging --- packages/@jsonql/ws/main.js | 16 ++++- packages/@jsonql/ws/main.js.map | 2 +- packages/@jsonql/ws/package.json | 2 +- .../init-websocket-client.js | 7 +- .../@jsonql/ws/tests/ws-client-auth.test.js | 13 ++-- packages/ws-server/client.js | 29 +++++++- packages/ws-server/src/intercom-methods.js | 69 +++++++++++++++++++ 7 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 packages/ws-server/src/intercom-methods.js diff --git a/packages/@jsonql/ws/main.js b/packages/@jsonql/ws/main.js index 3c5dba5f..cc0bd5f0 100644 --- a/packages/@jsonql/ws/main.js +++ b/packages/@jsonql/ws/main.js @@ -8081,10 +8081,20 @@ function initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) { ws.onmessage = function onMessageCallback(payload) { try { var header = extractPingResult(payload.data); - // terminate the client - ws.terminate(); + // return the new one with csrf header - resolver(new WebSocket(url, Object.assign(wsOptions, header))); + // @BUG too quick and kill the socket? + setTimeout(function () { + var newWs = new WebSocket(url, Object.assign(wsOptions, header)); + + newWs.onerror = function(err) { + console.log("newWs onerror", err); + }; + resolver(newWs); + + // terminate the client + ws.terminate(); + }, 100); } catch(e) { rejecter(e); } diff --git a/packages/@jsonql/ws/main.js.map b/packages/@jsonql/ws/main.js.map index 14efc2ec..3f625fd8 100644 --- a/packages/@jsonql/ws/main.js.map +++ b/packages/@jsonql/ws/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","sources":["node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/lodash-es/_arrayMap.js","../../ws-client-core/node_modules/lodash-es/isArray.js","../../ws-client-core/node_modules/lodash-es/_objectToString.js","../../ws-client-core/node_modules/lodash-es/isObjectLike.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-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/lodash-es/_overArg.js","../../ws-client-core/node_modules/jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/jsonql-params-validator/src/validator.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/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-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-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/node_modules/jsonql-utils/src/generic.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/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-send-method.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/setup-intercom.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/share/create-nsp-clients.js","../../ws-client-core/src/share/trigger-namespaces-on-error.js","../../ws-client-core/src/share/client-event-handler.js","../../ws-client-core/src/share/intercom-methods.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.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/login-event-handler.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/create-nsp/bind-socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.js","src/node-ws-client.js"],"sourcesContent":["export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * 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","// 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","/**\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","// 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","// 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","// 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","/**\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","/** 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","// 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","// 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","// 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// generic placeholder function\nexport const nil = () => false\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/**\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","// 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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log))\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/**\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 createNamespaceErrorHandler(client, opts, ee, nspGroup) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the clientitself\n objDefineProps(client, ON_ERROR_FN_NAME, 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 opts,\n ee\n ]\n}\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 createOnReadyHandler(client, opts, ee) {\n return [\n objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n} from './resolver-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 generator(opts, nspMap, ee) {\n\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n ]\n if (opts.enableAuth) {\n args.push(\n createAuthMethods\n )\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n args.push(setupFinalStep)\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n\n return fn(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 { generator } from './core'\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} frameworkSocketEngine \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(frameworkSocketEngine, config) {\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`jsonql-ws-core-client init error`, err)\n })\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} frameworkSocketEngine 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(frameworkSocketEngine, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(opts => wsClientCoreAction(frameworkSocketEngine, opts))\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}","// 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\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, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event handler 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 */\nconst notLoginWsHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n log('[notLoginHandler] 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 handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nconst getPrivateNamespace = (namespaces) => (\n namespaces.length > 1 ? namespaces[0] : false\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 */\nconst logoutEvtHandler = (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(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() {\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 handler\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the handler 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 notLoginWsHandler(privateNamespace, ee, opts)\n })\n}\n\n/**\n * A Event handler 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 */\nconst disconnectedHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedHandlerCallback(resolverName, args) {\n log(`[disconnectedHandler] 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 handler, 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 handler, 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 */\nconst disconnectHandler = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() {\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 disconnectedHandler(namespace, ee, opts)\n })\n })\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts \n * @param {object} ee Event Emitter instance\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 clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) {\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 let isPrivate = false\n let hasPrivate = false\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run in order here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace\n if (!hasPrivate) {\n hasPrivate = isPrivate\n }\n // log(namespace, ' --> nsps --> ', nsps[namespace])\n if (nsps[namespace]) {\n\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n Reflect.apply(bindSocketEventHandler, null, args)\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 notLoginWsHandler(namespace, ee, opts)\n }\n })\n // logout event handler \n if (hasPrivate) {\n log(`Has private and add logoutEvtHandler`)\n logoutEvtHandler(nsps, namespaces, ee, opts)\n }\n // finally the disconnect event handlers\n disconnectHandler(nsps, namespaces, ee, opts) \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 * 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 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 json = toJson(payload)\n const result = extractWsPayload(json)\n if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\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 createInitPing, \n extractPingResult, \n createIntercomPayload \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 // terminate the client \n ws.terminate()\n // return the new one with csrf header\n resolver(new WebSocket(url, Object.assign(wsOptions, header)))\n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\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 new Promise((resolver, rejecter) => { \n \n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\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\n log(`nspAuthClient: \\n${_url}\\n`, wsOptions)\n\n return new Promise((resolver, rejecter) => {\n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\n }\n}\n\nexport { initWebSocketClient }","/** 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","// @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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError,\n createIntercomPayload\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nconst logoutEventHandler = (ee, ws) => {\n // @TODO we need find a way to get the userdata \n ws.send(createIntercomPayload(LOGOUT_EVENT_NAME))\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() {\n try {\n log('terminate ws connection')\n ws.terminate()\n } catch(e) {\n console.error('ws.terminate error', e)\n }\n })\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\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventHandler(ee, ws)\n }\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventHandler } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // arguments for clientEventHandler\n const args = [opts, nspMap, ee, bindSocketEventHandler]\n // now create the nsps\n // const { namespaces } = nspMap\n const { token } = opts\n\n return createNspAction(opts, nspMap, token)\n .then(nsps => {\n args.push(nsps)\n Reflect.apply(clientEventHandler, null, args)\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n }) \n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\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 * @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 opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log) \n // @1.0.7 remove later once everything fixed \n \n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ No newline at end of file +{"version":3,"file":"main.js","sources":["node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/lodash-es/_arrayMap.js","../../ws-client-core/node_modules/lodash-es/isArray.js","../../ws-client-core/node_modules/lodash-es/_objectToString.js","../../ws-client-core/node_modules/lodash-es/isObjectLike.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-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/lodash-es/_overArg.js","../../ws-client-core/node_modules/jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/jsonql-params-validator/src/validator.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/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-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-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/node_modules/jsonql-utils/src/generic.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/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-send-method.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/setup-intercom.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/share/create-nsp-clients.js","../../ws-client-core/src/share/trigger-namespaces-on-error.js","../../ws-client-core/src/share/client-event-handler.js","../../ws-client-core/src/share/intercom-methods.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.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/login-event-handler.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/create-nsp/bind-socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.js","src/node-ws-client.js"],"sourcesContent":["export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * 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","// 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","/**\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","// 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","// 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","// 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","/**\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","/** 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","// 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","// 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","// 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// generic placeholder function\nexport const nil = () => false\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/**\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","// 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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log))\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/**\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 createNamespaceErrorHandler(client, opts, ee, nspGroup) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the clientitself\n objDefineProps(client, ON_ERROR_FN_NAME, 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 opts,\n ee\n ]\n}\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 createOnReadyHandler(client, opts, ee) {\n return [\n objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n} from './resolver-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 generator(opts, nspMap, ee) {\n\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n ]\n if (opts.enableAuth) {\n args.push(\n createAuthMethods\n )\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n args.push(setupFinalStep)\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n\n return fn(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 { generator } from './core'\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} frameworkSocketEngine \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(frameworkSocketEngine, config) {\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`jsonql-ws-core-client init error`, err)\n })\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} frameworkSocketEngine 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(frameworkSocketEngine, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(opts => wsClientCoreAction(frameworkSocketEngine, opts))\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}","// 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\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, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event handler 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 */\nconst notLoginWsHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n log('[notLoginHandler] 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 handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nconst getPrivateNamespace = (namespaces) => (\n namespaces.length > 1 ? namespaces[0] : false\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 */\nconst logoutEvtHandler = (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(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() {\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 handler\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the handler 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 notLoginWsHandler(privateNamespace, ee, opts)\n })\n}\n\n/**\n * A Event handler 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 */\nconst disconnectedHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedHandlerCallback(resolverName, args) {\n log(`[disconnectedHandler] 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 handler, 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 handler, 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 */\nconst disconnectHandler = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() {\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 disconnectedHandler(namespace, ee, opts)\n })\n })\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts \n * @param {object} ee Event Emitter instance\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 clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) {\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 let isPrivate = false\n let hasPrivate = false\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run in order here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace\n if (!hasPrivate) {\n hasPrivate = isPrivate\n }\n // log(namespace, ' --> nsps --> ', nsps[namespace])\n if (nsps[namespace]) {\n\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n Reflect.apply(bindSocketEventHandler, null, args)\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 notLoginWsHandler(namespace, ee, opts)\n }\n })\n // logout event handler \n if (hasPrivate) {\n log(`Has private and add logoutEvtHandler`)\n logoutEvtHandler(nsps, namespaces, ee, opts)\n }\n // finally the disconnect event handlers\n disconnectHandler(nsps, namespaces, ee, opts) \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 * 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 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 json = toJson(payload)\n const result = extractWsPayload(json)\n if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\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 createInitPing, \n extractPingResult, \n createIntercomPayload \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 \n // return the new one with csrf header\n // @BUG too quick and kill the socket?\n setTimeout(() => {\n const newWs = new WebSocket(url, Object.assign(wsOptions, header)) \n\n newWs.onerror = function(err) {\n console.log(`newWs onerror`, err)\n }\n resolver(newWs)\n\n // terminate the client \n ws.terminate()\n }, 100)\n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\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 new Promise((resolver, rejecter) => { \n \n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\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\n log(`nspAuthClient: \\n${_url}\\n`, wsOptions)\n\n return new Promise((resolver, rejecter) => {\n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\n }\n}\n\nexport { initWebSocketClient }","/** 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","// @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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError,\n createIntercomPayload\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nconst logoutEventHandler = (ee, ws) => {\n // @TODO we need find a way to get the userdata \n ws.send(createIntercomPayload(LOGOUT_EVENT_NAME))\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() {\n try {\n log('terminate ws connection')\n ws.terminate()\n } catch(e) {\n console.error('ws.terminate error', e)\n }\n })\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\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventHandler(ee, ws)\n }\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventHandler } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // arguments for clientEventHandler\n const args = [opts, nspMap, ee, bindSocketEventHandler]\n // now create the nsps\n // const { namespaces } = nspMap\n const { token } = opts\n\n return createNspAction(opts, nspMap, token)\n .then(nsps => {\n args.push(nsps)\n Reflect.apply(clientEventHandler, null, args)\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n }) \n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\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 * @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 opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log) \n // @1.0.7 remove later once everything fixed \n \n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ No newline at end of file diff --git a/packages/@jsonql/ws/package.json b/packages/@jsonql/ws/package.json index b7633305..add15c5b 100644 --- a/packages/@jsonql/ws/package.json +++ b/packages/@jsonql/ws/package.json @@ -29,7 +29,7 @@ "test:browser:auth": "npm run build:umd && DEBUG=jsonql-ws-* NODE_ENV=ws-auth node ./tests/browser/run-qunit.js", "test:opt": "ava ./tests/opt.test.js", "test:basic": "npm run build:cjs && DEBUG=jsonql-ws-* ava ./tests/ws-client-basic.test.js", - "test:auth": "npm run build:cjs && DEBUG=jsonql-ws-client* ava ./tests/ws-client-auth.test.js", + "test:auth": "npm run build:cjs && DEBUG=jsonql-ws-* ava ./tests/ws-client-auth.test.js", "test:login": "npm run build:cjs && DEBUG=jsonql-ws* ava ./tests/ws-client-auth-login.test.js", "test:chain": "npm run build:cjs && DEBUG=jsonql-ws-client* ava ./tests/ws-client-chain.test.js", "test:int": "npm run build:cjs && DEBUG=jsonql-ws-client* ava ./tests/integration.test.js", 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 f91a6b8c..b9a7d140 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 @@ -30,7 +30,11 @@ function initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) { // terminate the client ws.terminate() // return the new one with csrf header - resolver(new WebSocket(url, Object.assign(wsOptions, header))) + // @BUG too quick and kill the socket? + setTimeout(() => { + const newWs = new WebSocket(url, Object.assign(wsOptions, header)) + resolver(newWs) + }, 50) } catch(e) { rejecter(e) } @@ -59,6 +63,7 @@ function initWebSocketClient(WebSocket, auth, log) { */ return function createWsClient(url, wsOptions = {}) { const _url = fixWss(url) + log(`nspClient: \n${_url}\n`, wsOptions) return new Promise((resolver, rejecter) => { diff --git a/packages/@jsonql/ws/tests/ws-client-auth.test.js b/packages/@jsonql/ws/tests/ws-client-auth.test.js index ed9f7a99..a44b8efe 100644 --- a/packages/@jsonql/ws/tests/ws-client-auth.test.js +++ b/packages/@jsonql/ws/tests/ws-client-auth.test.js @@ -15,12 +15,15 @@ const contractDir = join(__dirname, 'fixtures', 'contract', 'auth') const contract = fsx.readJsonSync(join(contractDir, 'contract.json')) const publicContract = fsx.readJsonSync(join(contractDir, 'public-contract.json')) -const debug = require('debug')('jsonql-ws-client:test:ws-auth') +const _debug = require('debug')('jsonql-ws-client:test:ws-auth') const colors = require('colors/safe') -const localDebug = (str, ...args) => { +const debug = (str, ...args) => { + Reflect.apply(_debug, null, [colors.black.bgBrightMagenta(str+'')].concat(args)) +} - Reflect.apply(debug, null, [ colors.black.brightGreenBg(str+'') ].concat(args) ) +const localDebug = (str, ...args) => { + Reflect.apply(debug, null, [ colors.black.bgBrightGreen(str+'') ].concat(args) ) } const payload = {name: 'Joel'} @@ -84,7 +87,9 @@ test.serial.cb('It should able to connect to the WebSocket public namespace', t client.pinging('Hello') client.pinging.onResult = res => { - debug('res', res) + + localDebug('res', res) + t.is(res, 'connection established') client.pinging.send = 'ping'; } diff --git a/packages/ws-server/client.js b/packages/ws-server/client.js index 089c1b01..d84d7b7c 100644 --- a/packages/ws-server/client.js +++ b/packages/ws-server/client.js @@ -9,7 +9,34 @@ const { TOKEN_PARAM_NAME } = require('jsonql-constants') * @param {object} [opts = {}] pass init options to it * @return {object} ws instance */ -module.exports = function client(url, token = false, opts = {}) { +function basicClient(url, token = false, opts = {}) { let uri = token ? `${url}?${TOKEN_PARAM_NAME}=${token}` : url return new WebSocket(uri, opts) } + +/** + * Full client with the CSRF token features, and return as promise + * @param {*} url + * @param {*} token + * @param {*} opts + * @return {promise} resolve the verify connected client + */ +function fullClient(url, token = false, opts = {}) { + + return new Promise((resolver, rejecter) => { + const bc = basicClient(url, token, opts) + bc.onopen = function() { + + } + + bc.onerror = function(err) { + rejecter(err) + } + }) + +} + + + +// breaking change export as name +module.exports = { basicClient, fullClient } \ No newline at end of file diff --git a/packages/ws-server/src/intercom-methods.js b/packages/ws-server/src/intercom-methods.js new file mode 100644 index 00000000..96cc517f --- /dev/null +++ b/packages/ws-server/src/intercom-methods.js @@ -0,0 +1,69 @@ +// this will be part of the init client sequence +// as soon as we create a ws client +// we listen to the on.connect event +// then we send a init-ping event back to the server +// and server issue a csrf token back to use +// we use this token to create a new client and destroy the old one +const { + INTERCOM_RESOLVER_NAME, + SOCKET_PING_EVENT_NAME, + HEADERS_KEY, + DATA_KEY, + CSRF_HEADER_KEY +} = require( 'jsonql-constants') +const { + createQueryStr, + extractWsPayload, + timestamp, + toJson +} = require( 'jsonql-utils') +const { + JsonqlError +} = require( 'jsonql-errors') +const CSRF_HEADER_NOT_EXIST_ERR = 'CSRF header is not in the received payload' + +/** + * call the server to get a csrf token + * @return {string} formatted payload to send to the server + */ +function createInitPing() { + const ts = timestamp() + return createQueryStr(INTERCOM_RESOLVER_NAME, [SOCKET_PING_EVENT_NAME, ts]) +} + +/** + * Take the raw on.message result back then decoded it + * @param {*} payload the raw result = require( server + * @return {object} the csrf payload + */ +function extractPingResult(payload) { + const json = toJson(payload) + const result = extractWsPayload(json) + if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) { + return { + [HEADERS_KEY]: result[DATA_KEY] + } + } + throw new JsonqlError('extractPingResult', CSRF_HEADER_NOT_EXIST_ERR) +} + + +/** + * Create a generic intercom method + * @param {string} type the event type + * @param {array} args if any + * @return {string} formatted payload to send + */ +function createIntercomPayload(type, ...args) { + const ts = timestamp() + let payload = [type].concat(args) + payload.push(ts) + return createQueryStr(INTERCOM_RESOLVER_NAME, payload) +} + + +module.exports = { + createInitPing, + extractPingResult, + createIntercomPayload +} \ No newline at end of file -- Gitee From 64291309a35bfacc708378587d8084d6603534a2 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 09:27:17 +0800 Subject: [PATCH 14/66] Finish the test client --- packages/ws-server/client.js | 58 +++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/packages/ws-server/client.js b/packages/ws-server/client.js index d84d7b7c..8cdf499c 100644 --- a/packages/ws-server/client.js +++ b/packages/ws-server/client.js @@ -1,7 +1,11 @@ // we also provide a node client here const WebSocket = require('ws') const { TOKEN_PARAM_NAME } = require('jsonql-constants') - +const { JsonqlError } = require('jsonql-errors') +const { + createInitPing, + extractPingResult +} = require('./src/intercom-methods') /** * Create a client with auth token * @param {string} url start with ws:// @TODO check this? @@ -14,6 +18,34 @@ function basicClient(url, token = false, opts = {}) { return new WebSocket(uri, opts) } +/** + * Wrap the first init-ping in one place just resolve the message + * @param {*} ws + * @return {promise} + */ +function initConnect(ws) { + return new Promise((resolver, rejecter) => { + ws.onopen = function() { + ws.send(createInitPing()) + } + + ws.onmessage = function(payload) { + try { + ws.terminate() + resolver(extractPingResult(payload.data)) + } catch(e) { + rejecter(new JsonqlError('fullClient.onmessage', e)) + } + } + + ws.onerror = function(err) { + rejecter(err) + } + }) +} + + + /** * Full client with the CSRF token features, and return as promise * @param {*} url @@ -21,22 +53,26 @@ function basicClient(url, token = false, opts = {}) { * @param {*} opts * @return {promise} resolve the verify connected client */ -function fullClient(url, token = false, opts = {}) { +function fullClient(url, token = false, opts = {}, log) { return new Promise((resolver, rejecter) => { const bc = basicClient(url, token, opts) - bc.onopen = function() { - - } - bc.onerror = function(err) { - rejecter(err) - } - }) + return initConnect(bc) + .then(header => { + const config = Object.assign({}, opts, header) + + log(`config`, config) + + const client = basicClient(url, token, config) + resolver(client) + }) + .catch(err => { + rejecter(err) + }) + }) } - - // breaking change export as name module.exports = { basicClient, fullClient } \ No newline at end of file -- Gitee From ab23e4311e019c4e902417b4c75ff7b758a890f5 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 09:53:47 +0800 Subject: [PATCH 15/66] The problem is in the csrf exchange some how it just fucked --- packages/ws-server/client.js | 11 ++++---- packages/ws-server/tests/ws-jwt-auth.test.js | 28 ++++++++++++++------ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/packages/ws-server/client.js b/packages/ws-server/client.js index 8cdf499c..a9bca06d 100644 --- a/packages/ws-server/client.js +++ b/packages/ws-server/client.js @@ -6,6 +6,7 @@ const { createInitPing, extractPingResult } = require('./src/intercom-methods') +const debug = require('debug')('jsonql-ws-server:client') /** * Create a client with auth token * @param {string} url start with ws:// @TODO check this? @@ -31,7 +32,9 @@ function initConnect(ws) { ws.onmessage = function(payload) { try { - ws.terminate() + + // ws.close() + resolver(extractPingResult(payload.data)) } catch(e) { rejecter(new JsonqlError('fullClient.onmessage', e)) @@ -44,8 +47,6 @@ function initConnect(ws) { }) } - - /** * Full client with the CSRF token features, and return as promise * @param {*} url @@ -53,7 +54,7 @@ function initConnect(ws) { * @param {*} opts * @return {promise} resolve the verify connected client */ -function fullClient(url, token = false, opts = {}, log) { +function fullClient(url, token = false, opts = {}) { return new Promise((resolver, rejecter) => { const bc = basicClient(url, token, opts) @@ -62,7 +63,7 @@ function fullClient(url, token = false, opts = {}, log) { .then(header => { const config = Object.assign({}, opts, header) - log(`config`, config) + debug(`config`, config) const client = basicClient(url, token, config) diff --git a/packages/ws-server/tests/ws-jwt-auth.test.js b/packages/ws-server/tests/ws-jwt-auth.test.js index e0dd55ac..b97dc75c 100644 --- a/packages/ws-server/tests/ws-jwt-auth.test.js +++ b/packages/ws-server/tests/ws-jwt-auth.test.js @@ -4,9 +4,8 @@ const fsx = require('fs-extra') const colors = require('colors/safe') // this will get the umd version of the client module const { JSONQL_PATH } = require('jsonql-constants') -// const { decodeToken } = require('jsonql-jwt') -const wsNodeClient = require('../client') +const { fullClient, basicClient } = require('../client') const { extractWsPayload } = require('jsonql-ws-server-core') const serverSetup = require('./fixtures/server') const createToken = require('./fixtures/token') @@ -41,8 +40,14 @@ test.before(async t => { t.context.app.listen(port) // @1.3.0 there is no different between the two only need the token param now - t.context.client_public = wsNodeClient(baseUrl + 'public') - t.context.client_private = wsNodeClient(baseUrl + 'private', t.context.token) + // t.context.client_public = await fullClient(baseUrl + 'public') + // t.context.client_private = await fullClient(baseUrl + 'private', t.context.token) + + + t.context.client_private = basicClient(baseUrl + 'private', t.context.token) + t.context.client_public = basicClient(baseUrl + 'public') + // t.context.client_private_1 = await fullClient(baseUrl + 'private', t.context.token) + }) test.after(t => { @@ -87,9 +92,14 @@ test.cb('It should able to connect to the private namespace', t => { t.truthy(json.data) client.close() - debug(json) + debug('second json', json) t.end() }) + /* + t.context.client_private_1.on('open', () => { + t.end() + }) + */ }) // @NOTE when we run this in serial, it could hang up. @@ -102,7 +112,7 @@ test.cb(`first try to connect to the private without login and see what happens` let ctn = 0 // crash out the client - let authClient = wsNodeClient(baseUrl + 'private') + let authClient = basicClient(baseUrl + 'private') // this is useful we could add this to the client to handle the error authClient.on('error', err => { debug(rainbow(`Got error`), err) @@ -111,7 +121,9 @@ test.cb(`first try to connect to the private without login and see what happens` // next try to connect to the public again and see what happen - let pClient = wsNodeClient(baseUrl + 'public') + let pClient = basicClient(baseUrl + 'public') + + pClient.on('open', () => { debug(rainbow(`onopen`)) pClient.send( createPayload('availableToEveryone') ) @@ -128,7 +140,7 @@ test.cb(`first try to connect to the private without login and see what happens` setTimeout(() => { - authClient = wsNodeClient(baseUrl + 'private', t.context.token1) + authClient = basicClient(baseUrl + 'private', t.context.token1) authClient.on('message', data => { ++ctn let json = extractWsPayload(data) -- Gitee From 5ab3d6f161ac1a6a7ecfb0f53da61bf1b3f6bbd0 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 10:16:58 +0800 Subject: [PATCH 16/66] small update but nothing is fixed --- packages/ws-server-core/package.json | 2 +- packages/ws-server/src/modules.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/ws-server-core/package.json b/packages/ws-server-core/package.json index 581787bf..a7d10622 100644 --- a/packages/ws-server-core/package.json +++ b/packages/ws-server-core/package.json @@ -36,7 +36,7 @@ "jsonql-jwt": "^1.3.10", "jsonql-params-validator": "^1.6.1", "jsonql-resolver": "^1.1.3", - "jsonql-utils": "^1.2.0", + "jsonql-utils": "^1.2.1", "lodash": "^4.17.15", "nanoid": "^2.1.11", "node-cache": "^5.1.0" diff --git a/packages/ws-server/src/modules.js b/packages/ws-server/src/modules.js index 36b4819f..276c8739 100644 --- a/packages/ws-server/src/modules.js +++ b/packages/ws-server/src/modules.js @@ -19,8 +19,9 @@ const { SOCKET_STATE_KEY, getSocketHandler -} = require('jsonql-ws-server-core') -// require('../../ws-server-core') +} = require('../../ws-server-core') +// require('jsonql-ws-server-core') + module.exports = { WebSocket, -- Gitee From c183872230f66d63e4a62ceb1ad210eb6a7ecd1e Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 10:17:39 +0800 Subject: [PATCH 17/66] jsonql-ws-server-core 0.7.7 --- packages/ws-server-core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ws-server-core/package.json b/packages/ws-server-core/package.json index a7d10622..5377eb35 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.7.6", + "version": "0.7.7", "description": "This is the core module that drive the Jsonql WS Socket server, not for direct use.", "main": "index.js", "files": [ -- Gitee From 42ec4f5d4dc058322b59382ecee2ae20c3c87174 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 10:27:38 +0800 Subject: [PATCH 18/66] update all tests and passed --- packages/ws-server/package.json | 4 ++-- packages/ws-server/src/modules.js | 4 ++-- packages/ws-server/tests/basic.test.js | 6 +++--- packages/ws-server/tests/init.test.js | 6 +++--- packages/ws-server/tests/send.test.js | 4 ++-- packages/ws-server/tests/ws-connect-error.test.js | 4 ++-- packages/ws-server/tests/ws-connect-es6.test.js | 4 ++-- packages/ws-server/tests/ws-connect.test.js | 4 ++-- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json index 95684555..c576c1c8 100755 --- a/packages/ws-server/package.json +++ b/packages/ws-server/package.json @@ -34,8 +34,8 @@ "colors": "^1.4.0", "debug": "^4.1.1", "jsonql-constants": "^2.0.4", - "jsonql-utils": "^1.2.0", - "jsonql-ws-server-core": "^0.7.6", + "jsonql-utils": "^1.2.1", + "jsonql-ws-server-core": "^0.7.7", "ws": "^7.2.3" }, "devDependencies": { diff --git a/packages/ws-server/src/modules.js b/packages/ws-server/src/modules.js index 276c8739..3370f107 100644 --- a/packages/ws-server/src/modules.js +++ b/packages/ws-server/src/modules.js @@ -19,8 +19,8 @@ const { SOCKET_STATE_KEY, getSocketHandler -} = require('../../ws-server-core') -// require('jsonql-ws-server-core') +} = require('jsonql-ws-server-core') +// require('../../ws-server-core') module.exports = { diff --git a/packages/ws-server/tests/basic.test.js b/packages/ws-server/tests/basic.test.js index 5d0cf73c..eda0cdbe 100644 --- a/packages/ws-server/tests/basic.test.js +++ b/packages/ws-server/tests/basic.test.js @@ -7,7 +7,7 @@ const colors = require('colors/safe') const { JSONQL_PATH } = require('jsonql-constants') // const { decodeToken } = require('jsonql-jwt') -const wsNodeClient = require('../client') +const { basicClient } = require('../client') const { extractWsPayload } = require('jsonql-ws-server-core') const serverSetup = require('./fixtures/server') const createToken = require('./fixtures/token') @@ -42,8 +42,8 @@ test.before(async t => { t.context.app.listen(port) // @1.3.0 there is no different between the two only need the token param now - t.context.client_public = wsNodeClient(baseUrl + 'public') - t.context.client_private = wsNodeClient(baseUrl + 'private', t.context.token) + t.context.client_public = basicClient(baseUrl + 'public') + t.context.client_private = basicClient(baseUrl + 'private', t.context.token) }) test.after(t => { diff --git a/packages/ws-server/tests/init.test.js b/packages/ws-server/tests/init.test.js index c42c41a6..328d4ad6 100644 --- a/packages/ws-server/tests/init.test.js +++ b/packages/ws-server/tests/init.test.js @@ -4,7 +4,7 @@ const test = require('ava') const { join } = require('path') const fsx = require('fs-extra') -const wsNodeClient = require('../client') +const { basicClient } = require('../client') const wsServer = require('./fixtures/server') const { @@ -32,7 +32,7 @@ test.before(async t => { t.context.io = io t.context.server = app t.context.server.listen(port) - t.context.client = wsNodeClient(`ws://localhost:${port}/${JSONQL_PATH}`) + t.context.client = basicClient(`ws://localhost:${port}/${JSONQL_PATH}`) }) test.after(t => { @@ -57,7 +57,7 @@ test.cb(`Testing the init ping call`, t => { // t.end() // reinit the client with an options - const newClient = wsNodeClient(`ws://localhost:${port}/${JSONQL_PATH}`, false, {headers: json.data}) + const newClient = basicClient(`ws://localhost:${port}/${JSONQL_PATH}`, false, {headers: json.data}) newClient.on('open', () => { t.end() diff --git a/packages/ws-server/tests/send.test.js b/packages/ws-server/tests/send.test.js index 82baae76..09237870 100644 --- a/packages/ws-server/tests/send.test.js +++ b/packages/ws-server/tests/send.test.js @@ -2,7 +2,7 @@ const test = require('ava') const { join } = require('path') const fsx = require('fs-extra') -const wsNodeClient = require('../client') +const { basicClient } = require('../client') const wsServer = require('./fixtures/server') const { JSONQL_PATH } = require('jsonql-constants') const { extractWsPayload } = require('jsonql-ws-server-core') @@ -23,7 +23,7 @@ test.before(async t => { t.context.io = io t.context.server = app t.context.server.listen(port) - t.context.client = wsNodeClient(`ws://localhost:${port}/${JSONQL_PATH}`) + t.context.client = basicClient(`ws://localhost:${port}/${JSONQL_PATH}`) }) test.after(t => { diff --git a/packages/ws-server/tests/ws-connect-error.test.js b/packages/ws-server/tests/ws-connect-error.test.js index 52f51193..a6e4ff1a 100644 --- a/packages/ws-server/tests/ws-connect-error.test.js +++ b/packages/ws-server/tests/ws-connect-error.test.js @@ -4,7 +4,7 @@ const test = require('ava') const { join } = require('path') const fsx = require('fs-extra') -const wsNodeClient = require('../client') +const { basicClient } = require('../client') const wsServer = require('./fixtures/server') const { JSONQL_PATH, ERROR_KEY } = require('jsonql-constants') @@ -29,7 +29,7 @@ test.before(async t => { t.context.server = app t.context.server.listen(port) - t.context.client = wsNodeClient(`ws://localhost:${port}/${JSONQL_PATH}`) + t.context.client = basicClient(`ws://localhost:${port}/${JSONQL_PATH}`) }) test.after(t => { diff --git a/packages/ws-server/tests/ws-connect-es6.test.js b/packages/ws-server/tests/ws-connect-es6.test.js index 364f0d79..f1c9dbe3 100644 --- a/packages/ws-server/tests/ws-connect-es6.test.js +++ b/packages/ws-server/tests/ws-connect-es6.test.js @@ -4,7 +4,7 @@ const test = require('ava') const { join } = require('path') const fsx = require('fs-extra') -const wsNodeClient = require('../client') +const { basicClient } = require('../client') const wsServer = require('./fixtures/server') const { JSONQL_PATH, ERROR_KEY } = require('jsonql-constants') @@ -31,7 +31,7 @@ test.before(async t => { t.context.server = app; t.context.server.listen(port) - t.context.client = wsNodeClient(`ws://localhost:${port}/${JSONQL_PATH}`) + t.context.client = basicClient(`ws://localhost:${port}/${JSONQL_PATH}`) }) test.after(t => { diff --git a/packages/ws-server/tests/ws-connect.test.js b/packages/ws-server/tests/ws-connect.test.js index 9d7d9338..82dfad61 100644 --- a/packages/ws-server/tests/ws-connect.test.js +++ b/packages/ws-server/tests/ws-connect.test.js @@ -4,7 +4,7 @@ const test = require('ava') const { join } = require('path') const fsx = require('fs-extra') -const wsNodeClient = require('../client') +const { basicClient } = require('../client') const wsServer = require('./fixtures/server') const { JSONQL_PATH } = require('jsonql-constants') @@ -28,7 +28,7 @@ test.before(async t => { t.context.io = io t.context.server = app t.context.server.listen(port) - t.context.client = wsNodeClient(`ws://localhost:${port}/${JSONQL_PATH}`) + t.context.client = basicClient(`ws://localhost:${port}/${JSONQL_PATH}`) }) test.after(t => { -- Gitee From 97afc7899aeb8a892a0315f70736496658227404 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 10:28:37 +0800 Subject: [PATCH 19/66] jsonql-ws-server 1.7.5 --- packages/ws-server/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json index c576c1c8..a0e3399c 100755 --- a/packages/ws-server/package.json +++ b/packages/ws-server/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-ws-server", - "version": "1.7.4", + "version": "1.7.5", "description": "Setup WebSocket server for the jsonql to run on the same host, automatic generate public / private channel using contract", "main": "index.js", "files": [ -- Gitee From e850ab2e30e28b46e509cefcfe2191cb27a84d0f Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 12:40:44 +0800 Subject: [PATCH 20/66] disable the csrf token now --- packages/@jsonql/ws/main.js | 226 +++--------------- packages/@jsonql/ws/main.js.map | 2 +- .../init-websocket-client.js | 14 +- packages/ws-client-core/package.json | 2 +- 4 files changed, 47 insertions(+), 197 deletions(-) diff --git a/packages/@jsonql/ws/main.js b/packages/@jsonql/ws/main.js index cc0bd5f0..333f5cb3 100644 --- a/packages/@jsonql/ws/main.js +++ b/packages/@jsonql/ws/main.js @@ -697,7 +697,6 @@ var checkIsAny = function(value, checkNull) { // the core stuff to id if it's calling with jsonql var DATA_KEY = 'data'; var ERROR_KEY = 'error'; -var HEADERS_KEY = 'headers'; var JSONQL_PATH = 'jsonql'; @@ -722,8 +721,6 @@ var LOGIN_FN_NAME = 'login'; var LOGOUT_FN_NAME = 'logout'; 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 @@ -754,24 +751,12 @@ var WS_OPT_PROP_KEY = 'wsOptions'; var CONTRACT_PROP_KEY = 'contract'; var TOKEN_PROP_KEY = 'token'; - - /* socket.js */ - -// the constants file is gettig too large -// we need to split up and group the related constant in one file -// also it makes the other module easiler to id what they are importing -// use throughout the clients -var SOCKET_PING_EVENT_NAME = '__ping__'; // when init connection do a ping var LOGIN_EVENT_NAME = '__login__'; var LOGOUT_EVENT_NAME = '__logout__'; var DISCONNECT_EVENT_NAME = '__disconnect__'; // instead of using an event name in place of resolverName in the param // we use this internal resolverName instead, and in type using the event names var INTERCOM_RESOLVER_NAME = '__intercom__'; -// for ws servers -var WS_REPLY_TYPE = '__reply__'; -var WS_EVT_NAME = '__event__'; -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'; @@ -6620,25 +6605,6 @@ var inArray$1 = function (arr, value) { return !!arr.filter(function (a) { retur // quick and dirty to turn non array to array var toArray$1 = function (arg) { return isArray(arg) ? arg : [arg]; }; -/** - * parse string to json or just return the original value if error happened - * @param {*} n input - * @param {boolean} [t=true] or throw - * @return {*} json object on success - */ -var parseJson = function(n, t) { - if ( t === void 0 ) t=true; - - try { - return JSON.parse(n) - } catch(e) { - if (t) { - return n - } - throw new Error(e) - } -}; - /** * @param {object} obj for search * @param {string} key target @@ -6666,18 +6632,6 @@ var createEvt = function () { return args.join('_'); }; -/** - * small util to make sure the return value is valid JSON object - * @param {*} n input - * @return {object} correct JSON object - */ -var toJson = function (n) { - if (typeof n === 'string') { - return parseJson(n) - } - return parseJson(JSON.stringify(n)) -}; - /** * Simple check if the prop is function * @param {*} prop input @@ -6983,57 +6937,6 @@ function getNspInfoByConfig(config) { return Object.assign(nspInfo, { namespaces: namespaces }) } -// There are the socket related methods ported back from - -var PAYLOAD_NOT_DECODED_ERR = 'payload can not decoded'; -var WS_KEYS = [ - WS_REPLY_TYPE, - WS_EVT_NAME, - WS_DATA_NAME -]; - -/** - * @param {string|object} payload should be string when reply but could be transformed - * @return {boolean} true is OK - */ -var isWsReply = function (payload) { - var json = isString(payload) ? toJson(payload) : payload; - var data = json.data; - if (data) { - var result = WS_KEYS.filter(function (key) { return isObjectHasKey$1(data, key); }); - return (result.length === WS_KEYS.length) ? data : false - } - return false -}; - -/** - * @param {string|object} data received data - * @param {function} [cb=nil] this is for extracting the TS field or when it's error - * @return {object} false on failed - */ -var extractWsPayload = function (payload, cb) { - if ( cb === void 0 ) cb = nil; - - try { - var json = toJson(payload); - // now handle the data - var _data; - if ((_data = isWsReply(json)) !== false) { - // note the ts property is on its own - cb(TIMESTAMP_PARAM_NAME, json[TIMESTAMP_PARAM_NAME]); - - return { - data: toJson(_data[WS_DATA_NAME]), - resolverName: _data[WS_EVT_NAME], - type: _data[WS_REPLY_TYPE] - } - } - throw new JsonqlError$1(PAYLOAD_NOT_DECODED_ERR, payload) - } catch(e) { - return cb(ERROR_KEY, e) - } -}; - // group all the small functions here @@ -7981,32 +7884,6 @@ function clientEventHandler$1(opts, nspMap, ee, bindSocketEventHandler, nsps) { } // this will be part of the init client sequence -var CSRF_HEADER_NOT_EXIST_ERR = 'CSRF header is not in the received payload'; - -/** - * call the server to get a csrf token - * @return {string} formatted payload to send to the server - */ -function createInitPing() { - var ts = timestamp(); - return createQueryStr(INTERCOM_RESOLVER_NAME, [SOCKET_PING_EVENT_NAME, ts]) -} - -/** - * Take the raw on.message result back then decoded it - * @param {*} payload the raw result from server - * @return {object} the csrf payload - */ -function extractPingResult(payload) { - var obj; - - var json = toJson(payload); - var result = extractWsPayload(json); - if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) { - return ( obj = {}, obj[HEADERS_KEY] = result[DATA_KEY], obj ) - } - throw new JsonqlError$1('extractPingResult', CSRF_HEADER_NOT_EXIST_ERR) -} /** @@ -8032,9 +7909,9 @@ var TIMESTAMP_PARAM_NAME$1 = 'TS'; var LOGIN_EVENT_NAME$1 = '__login__'; var LOGOUT_EVENT_NAME$1 = '__logout__'; // for ws servers -var WS_REPLY_TYPE$1 = '__reply__'; -var WS_EVT_NAME$1 = '__event__'; -var WS_DATA_NAME$1 = '__data__'; +var WS_REPLY_TYPE = '__reply__'; +var WS_EVT_NAME = '__event__'; +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$1 = 'onMessage'; @@ -8061,50 +7938,6 @@ var wsClientConstProps = { // pass the different type of ws to generate the client -/** - * Group the ping and get respond create new client in one - * @param {object} ws - * @param {object} WebSocket - * @param {string} url - * @param {function} resolver - * @param {function} rejecter - * @param {boolean} auth client or not - * @return {promise} resolve the confirm client - */ -function initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) { - // @TODO how to we id this client can issue a CSRF - // by origin? - ws.onopen = function onOpenCallback() { - ws.send(createInitPing()); - }; - - ws.onmessage = function onMessageCallback(payload) { - try { - var header = extractPingResult(payload.data); - - // return the new one with csrf header - // @BUG too quick and kill the socket? - setTimeout(function () { - var newWs = new WebSocket(url, Object.assign(wsOptions, header)); - - newWs.onerror = function(err) { - console.log("newWs onerror", err); - }; - resolver(newWs); - - // terminate the client - ws.terminate(); - }, 100); - } catch(e) { - rejecter(e); - } - }; - - ws.onerror = function onErrorCallback(err) { - rejecter(err); - }; -} - /** * The bug was in the wsOptions where ws don't need it but socket.io do * therefore the object was pass as second parameter! @@ -8125,12 +7958,16 @@ function initWebSocketClient(WebSocket, auth, log) { if ( wsOptions === void 0 ) wsOptions = {}; var _url = fixWss(url); + log(("nspClient: \n" + _url + "\n"), wsOptions); return new Promise(function (resolver, rejecter) { var unconfirmClient = new WebSocket(_url, wsOptions); - initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions); + + resolver(unconfirmClient); + + // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) }) } } @@ -8153,7 +7990,10 @@ function initWebSocketClient(WebSocket, auth, log) { return new Promise(function (resolver, rejecter) { var unconfirmClient = new WebSocket(_url, wsOptions); - initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions); + + resolver(unconfirmClient); + + // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) }) } } @@ -10374,7 +10214,7 @@ var inArray$2 = function (arr, value) { return !!arr.filter(function (a) { retur * @param {boolean} [t=true] or throw * @return {*} json object on success */ -var parseJson$1 = function(n, t) { +var parseJson = function(n, t) { if ( t === void 0 ) t=true; try { @@ -10419,11 +10259,11 @@ var createEvt$1 = function () { * @param {*} n input * @return {object} correct JSON object */ -var toJson$1 = function (n) { +var toJson = function (n) { if (typeof n === 'string') { - return parseJson$1(n) + return parseJson(n) } - return parseJson$1(JSON.stringify(n)) + return parseJson(JSON.stringify(n)) }; // generic placeholder function @@ -10603,23 +10443,23 @@ function createQueryStr$1(resolverName, args, jsonp) { // There are the socket related methods ported back from -var PAYLOAD_NOT_DECODED_ERR$1 = 'payload can not decoded'; -var WS_KEYS$1 = [ - WS_REPLY_TYPE$1, - WS_EVT_NAME$1, - WS_DATA_NAME$1 +var PAYLOAD_NOT_DECODED_ERR = 'payload can not decoded'; +var WS_KEYS = [ + WS_REPLY_TYPE, + WS_EVT_NAME, + WS_DATA_NAME ]; /** * @param {string|object} payload should be string when reply but could be transformed * @return {boolean} true is OK */ -var isWsReply$1 = function (payload) { - var json = isString$3(payload) ? toJson$1(payload) : payload; +var isWsReply = function (payload) { + var json = isString$3(payload) ? toJson(payload) : payload; var data = json.data; if (data) { - var result = WS_KEYS$1.filter(function (key) { return isObjectHasKey$2(data, key); }); - return (result.length === WS_KEYS$1.length) ? data : false + var result = WS_KEYS.filter(function (key) { return isObjectHasKey$2(data, key); }); + return (result.length === WS_KEYS.length) ? data : false } return false }; @@ -10629,24 +10469,24 @@ var isWsReply$1 = function (payload) { * @param {function} [cb=nil] this is for extracting the TS field or when it's error * @return {object} false on failed */ -var extractWsPayload$1 = function (payload, cb) { +var extractWsPayload = function (payload, cb) { if ( cb === void 0 ) cb = nil$1; try { - var json = toJson$1(payload); + var json = toJson(payload); // now handle the data var _data; - if ((_data = isWsReply$1(json)) !== false) { + if ((_data = isWsReply(json)) !== false) { // note the ts property is on its own cb(TIMESTAMP_PARAM_NAME$1, json[TIMESTAMP_PARAM_NAME$1]); return { - data: toJson$1(_data[WS_DATA_NAME$1]), - resolverName: _data[WS_EVT_NAME$1], - type: _data[WS_REPLY_TYPE$1] + data: toJson(_data[WS_DATA_NAME]), + resolverName: _data[WS_EVT_NAME], + type: _data[WS_REPLY_TYPE] } } - throw new JsonqlError$2(PAYLOAD_NOT_DECODED_ERR$1, payload) + throw new JsonqlError$2(PAYLOAD_NOT_DECODED_ERR, payload) } catch(e) { return cb(ERROR_KEY$1, e) } @@ -10746,7 +10586,7 @@ function bindSocketEventHandler(namespace, ws, ee, isPrivate, opts) { // log(`ws.onmessage raw payload`, payload) // @TODO the payload actually contain quite a few things - is that changed? // type: message, data: data_send_from_server - var json = extractWsPayload$1(payload.data); + var json = extractWsPayload(payload.data); var resolverName = json.resolverName; var type = json.type; diff --git a/packages/@jsonql/ws/main.js.map b/packages/@jsonql/ws/main.js.map index 3f625fd8..279d3c87 100644 --- a/packages/@jsonql/ws/main.js.map +++ b/packages/@jsonql/ws/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","sources":["node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/lodash-es/_arrayMap.js","../../ws-client-core/node_modules/lodash-es/isArray.js","../../ws-client-core/node_modules/lodash-es/_objectToString.js","../../ws-client-core/node_modules/lodash-es/isObjectLike.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-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/lodash-es/_overArg.js","../../ws-client-core/node_modules/jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/jsonql-params-validator/src/validator.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/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-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-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/node_modules/jsonql-utils/src/generic.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/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-send-method.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/setup-intercom.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/share/create-nsp-clients.js","../../ws-client-core/src/share/trigger-namespaces-on-error.js","../../ws-client-core/src/share/client-event-handler.js","../../ws-client-core/src/share/intercom-methods.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.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/login-event-handler.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/create-nsp/bind-socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.js","src/node-ws-client.js"],"sourcesContent":["export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * 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","// 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","/**\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","// 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","// 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","// 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","/**\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","/** 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","// 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","// 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","// 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// generic placeholder function\nexport const nil = () => false\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/**\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","// 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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log))\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/**\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 createNamespaceErrorHandler(client, opts, ee, nspGroup) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the clientitself\n objDefineProps(client, ON_ERROR_FN_NAME, 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 opts,\n ee\n ]\n}\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 createOnReadyHandler(client, opts, ee) {\n return [\n objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n} from './resolver-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 generator(opts, nspMap, ee) {\n\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n ]\n if (opts.enableAuth) {\n args.push(\n createAuthMethods\n )\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n args.push(setupFinalStep)\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n\n return fn(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 { generator } from './core'\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} frameworkSocketEngine \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(frameworkSocketEngine, config) {\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`jsonql-ws-core-client init error`, err)\n })\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} frameworkSocketEngine 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(frameworkSocketEngine, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(opts => wsClientCoreAction(frameworkSocketEngine, opts))\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}","// 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\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, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event handler 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 */\nconst notLoginWsHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n log('[notLoginHandler] 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 handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nconst getPrivateNamespace = (namespaces) => (\n namespaces.length > 1 ? namespaces[0] : false\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 */\nconst logoutEvtHandler = (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(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() {\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 handler\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the handler 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 notLoginWsHandler(privateNamespace, ee, opts)\n })\n}\n\n/**\n * A Event handler 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 */\nconst disconnectedHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedHandlerCallback(resolverName, args) {\n log(`[disconnectedHandler] 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 handler, 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 handler, 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 */\nconst disconnectHandler = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() {\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 disconnectedHandler(namespace, ee, opts)\n })\n })\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts \n * @param {object} ee Event Emitter instance\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 clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) {\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 let isPrivate = false\n let hasPrivate = false\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run in order here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace\n if (!hasPrivate) {\n hasPrivate = isPrivate\n }\n // log(namespace, ' --> nsps --> ', nsps[namespace])\n if (nsps[namespace]) {\n\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n Reflect.apply(bindSocketEventHandler, null, args)\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 notLoginWsHandler(namespace, ee, opts)\n }\n })\n // logout event handler \n if (hasPrivate) {\n log(`Has private and add logoutEvtHandler`)\n logoutEvtHandler(nsps, namespaces, ee, opts)\n }\n // finally the disconnect event handlers\n disconnectHandler(nsps, namespaces, ee, opts) \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 * 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 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 json = toJson(payload)\n const result = extractWsPayload(json)\n if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\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 createInitPing, \n extractPingResult, \n createIntercomPayload \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 \n // return the new one with csrf header\n // @BUG too quick and kill the socket?\n setTimeout(() => {\n const newWs = new WebSocket(url, Object.assign(wsOptions, header)) \n\n newWs.onerror = function(err) {\n console.log(`newWs onerror`, err)\n }\n resolver(newWs)\n\n // terminate the client \n ws.terminate()\n }, 100)\n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\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 new Promise((resolver, rejecter) => { \n \n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\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\n log(`nspAuthClient: \\n${_url}\\n`, wsOptions)\n\n return new Promise((resolver, rejecter) => {\n const unconfirmClient = new WebSocket(_url, wsOptions)\n initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\n }\n}\n\nexport { initWebSocketClient }","/** 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","// @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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError,\n createIntercomPayload\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nconst logoutEventHandler = (ee, ws) => {\n // @TODO we need find a way to get the userdata \n ws.send(createIntercomPayload(LOGOUT_EVENT_NAME))\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() {\n try {\n log('terminate ws connection')\n ws.terminate()\n } catch(e) {\n console.error('ws.terminate error', e)\n }\n })\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\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventHandler(ee, ws)\n }\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventHandler } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // arguments for clientEventHandler\n const args = [opts, nspMap, ee, bindSocketEventHandler]\n // now create the nsps\n // const { namespaces } = nspMap\n const { token } = opts\n\n return createNspAction(opts, nspMap, token)\n .then(nsps => {\n args.push(nsps)\n Reflect.apply(clientEventHandler, null, args)\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n }) \n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\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 * @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 opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log) \n // @1.0.7 remove later once everything fixed \n \n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ No newline at end of file +{"version":3,"file":"main.js","sources":["node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arrayMap.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_objectToString.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isObjectLike.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseSlice.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseFindIndex.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseIsNaN.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_strictIndexOf.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_asciiToArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_hasUnicode.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_unicodeToArray.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/number.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/string.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/boolean.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/any.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/constants.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/combine.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/array.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_overArg.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/validator.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_listCacheClear.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/eq.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_stackDelete.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_stackGet.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_stackHas.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isObject.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_toSource.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_getValue.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_hashDelete.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_isKeyable.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_createBaseFor.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_copyArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_isPrototype.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isLength.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/stubFalse.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseUnary.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_safeGet.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseTimes.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_isIndex.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_nativeKeysIn.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/identity.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_apply.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/constant.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_shortOut.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_setCacheAdd.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_setCacheHas.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arraySome.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_cacheHas.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_mapToArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_setToArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arrayPush.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arrayFilter.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/stubArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_matchesStrictComparable.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseHasIn.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseProperty.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/negate.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseFindKey.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/is-in-array.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/enum-error.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/type-error.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/checker-error.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/run-validation.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/check-options-async.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/construct-config.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/index.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/index.js","../../ws-client-core/src/utils/get-log-fn.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/constants.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/store.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/utils.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/suspend.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/store-service.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/event-service.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/index.js","../../ws-client-core/src/utils/get-event-emitter.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/generic.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/contract.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/timestamp.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/params-api.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/namespace.js","../../ws-client-core/src/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-send-method.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/setup-intercom.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/share/create-nsp-clients.js","../../ws-client-core/src/share/trigger-namespaces-on-error.js","../../ws-client-core/src/share/client-event-handler.js","../../ws-client-core/src/share/intercom-methods.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.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/login-event-handler.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/create-nsp/bind-socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.js","src/node-ws-client.js"],"sourcesContent":["export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * 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","// 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","/**\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","// 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","// 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","// 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","/**\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","/** 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","// 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","// 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","// 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// generic placeholder function\nexport const nil = () => false\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/**\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","// 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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log))\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/**\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 createNamespaceErrorHandler(client, opts, ee, nspGroup) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the clientitself\n objDefineProps(client, ON_ERROR_FN_NAME, 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 opts,\n ee\n ]\n}\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 createOnReadyHandler(client, opts, ee) {\n return [\n objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n} from './resolver-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 generator(opts, nspMap, ee) {\n\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n ]\n if (opts.enableAuth) {\n args.push(\n createAuthMethods\n )\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n args.push(setupFinalStep)\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n\n return fn(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 { generator } from './core'\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} frameworkSocketEngine \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(frameworkSocketEngine, config) {\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`jsonql-ws-core-client init error`, err)\n })\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} frameworkSocketEngine 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(frameworkSocketEngine, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(opts => wsClientCoreAction(frameworkSocketEngine, opts))\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}","// 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\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, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event handler 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 */\nconst notLoginWsHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n log('[notLoginHandler] 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 handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nconst getPrivateNamespace = (namespaces) => (\n namespaces.length > 1 ? namespaces[0] : false\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 */\nconst logoutEvtHandler = (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(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() {\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 handler\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the handler 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 notLoginWsHandler(privateNamespace, ee, opts)\n })\n}\n\n/**\n * A Event handler 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 */\nconst disconnectedHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedHandlerCallback(resolverName, args) {\n log(`[disconnectedHandler] 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 handler, 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 handler, 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 */\nconst disconnectHandler = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() {\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 disconnectedHandler(namespace, ee, opts)\n })\n })\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts \n * @param {object} ee Event Emitter instance\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 clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) {\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 let isPrivate = false\n let hasPrivate = false\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run in order here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace\n if (!hasPrivate) {\n hasPrivate = isPrivate\n }\n // log(namespace, ' --> nsps --> ', nsps[namespace])\n if (nsps[namespace]) {\n\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n Reflect.apply(bindSocketEventHandler, null, args)\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 notLoginWsHandler(namespace, ee, opts)\n }\n })\n // logout event handler \n if (hasPrivate) {\n log(`Has private and add logoutEvtHandler`)\n logoutEvtHandler(nsps, namespaces, ee, opts)\n }\n // finally the disconnect event handlers\n disconnectHandler(nsps, namespaces, ee, opts) \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 * 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 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 json = toJson(payload)\n const result = extractWsPayload(json)\n if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\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 createInitPing, \n extractPingResult, \n createIntercomPayload \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 // the csrf cause all kinds of problem so we abandoned it for now\n return resolver(ws)\n /*\n // terminate the client \n ws.terminate()\n // return the new one with csrf header\n // @BUG too quick and kill the socket?\n setTimeout(() => {\n const newWs = new WebSocket(url, Object.assign(wsOptions, header)) \n resolver(newWs) \n }, 50)\n */\n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\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 \n log(`nspClient: \\n${_url}\\n`, wsOptions)\n\n return new Promise((resolver, rejecter) => { \n \n const unconfirmClient = new WebSocket(_url, wsOptions)\n \n resolver(unconfirmClient)\n\n // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\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\n log(`nspAuthClient: \\n${_url}\\n`, wsOptions)\n\n return new Promise((resolver, rejecter) => {\n const unconfirmClient = new WebSocket(_url, wsOptions)\n \n resolver(unconfirmClient)\n\n // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\n }\n}\n\nexport { initWebSocketClient }","/** 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","// @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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError,\n createIntercomPayload\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nconst logoutEventHandler = (ee, ws) => {\n // @TODO we need find a way to get the userdata \n ws.send(createIntercomPayload(LOGOUT_EVENT_NAME))\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() {\n try {\n log('terminate ws connection')\n ws.terminate()\n } catch(e) {\n console.error('ws.terminate error', e)\n }\n })\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\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventHandler(ee, ws)\n }\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventHandler } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // arguments for clientEventHandler\n const args = [opts, nspMap, ee, bindSocketEventHandler]\n // now create the nsps\n // const { namespaces } = nspMap\n const { token } = opts\n\n return createNspAction(opts, nspMap, token)\n .then(nsps => {\n args.push(nsps)\n Reflect.apply(clientEventHandler, null, args)\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n }) \n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\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 * @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 opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log) \n // @1.0.7 remove later once everything fixed \n \n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ 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 b9a7d140..cc523b05 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 @@ -27,6 +27,9 @@ function initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) { ws.onmessage = function onMessageCallback(payload) { try { const header = extractPingResult(payload.data) + // the csrf cause all kinds of problem so we abandoned it for now + return resolver(ws) + /* // terminate the client ws.terminate() // return the new one with csrf header @@ -35,6 +38,7 @@ function initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) { const newWs = new WebSocket(url, Object.assign(wsOptions, header)) resolver(newWs) }, 50) + */ } catch(e) { rejecter(e) } @@ -69,7 +73,10 @@ function initWebSocketClient(WebSocket, auth, log) { return new Promise((resolver, rejecter) => { const unconfirmClient = new WebSocket(_url, wsOptions) - initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) + + resolver(unconfirmClient) + + // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) }) } } @@ -90,7 +97,10 @@ function initWebSocketClient(WebSocket, auth, log) { return new Promise((resolver, rejecter) => { const unconfirmClient = new WebSocket(_url, wsOptions) - initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) + + resolver(unconfirmClient) + + // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) }) } } diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json index 009e1786..2d4aff61 100644 --- a/packages/ws-client-core/package.json +++ b/packages/ws-client-core/package.json @@ -65,7 +65,7 @@ "esm": "^3.2.25", "fs-extra": "^8.1.0", "jsonql-contract": "^1.8.10", - "jsonql-ws-server": "^1.7.4", + "jsonql-ws-server": "^1.7.5", "kefir": "^3.8.6", "ws": "^7.2.3" }, -- Gitee From fd4e185c872f320128500ce1026c6133c3581eac Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 13:15:23 +0800 Subject: [PATCH 21/66] move some of methods out and just keep a bear minimum --- packages/@jsonql/ws/main.js | 112 ++---------------- packages/@jsonql/ws/main.js.map | 2 +- .../create-nsp/bind-socket-event-handler.js | 9 +- .../src/core/create-nsp/create-nsp-action.js | 2 + .../src/share/client-event-handler.js | 81 +------------ .../src/share/event-listerners.js | 80 +++++++++++++ 6 files changed, 99 insertions(+), 187 deletions(-) create mode 100644 packages/ws-client-core/src/share/event-listerners.js diff --git a/packages/@jsonql/ws/main.js b/packages/@jsonql/ws/main.js index 333f5cb3..c9578c96 100644 --- a/packages/@jsonql/ws/main.js +++ b/packages/@jsonql/ws/main.js @@ -7074,8 +7074,6 @@ var EMIT_EVT = EMIT_REPLY_TYPE; var UNKNOWN_RESULT = 'UKNNOWN RESULT!'; var MY_NAMESPACE = 'myNamespace'; -// this is a socket only (for now) feature so we just put it here -var DISCONNECTED_ERROR_MSG = "You have disconnected from the socket server, please reconnect."; // breaking it up further to share between methods @@ -7688,22 +7686,6 @@ function createNspAuthClient(namespace, opts) { // this use by client-event-handler -/** - * trigger errors on all the namespace onError handler - * @param {object} ee Event Emitter - * @param {array} namespaces nsps string - * @param {string} message optional - * @return {void} - */ -function triggerNamespacesOnError(ee, namespaces, message) { - namespaces.forEach( function (namespace) { - ee.$trigger( - createEvt(namespace, ON_ERROR_FN_NAME), - [{ message: message, namespace: namespace }] - ); - }); -} - /** * Handle the onerror callback * @param {object} ee event emitter @@ -7749,85 +7731,6 @@ var getPrivateNamespace = function (namespaces) { return ( namespaces.length > 1 ? namespaces[0] : false ); }; -/** - * Only when there is a private namespace then we bind to this event - * @param {object} nsps the available nsp(s) - * @param {array} namespaces available namespace - * @param {object} ee eventEmitter - * @param {object} opts configuration - * @return {void} - */ -var logoutEvtHandler = function (nsps, namespaces, ee, opts) { - var log = opts.log; - // this will be available regardless enableAuth - // because the server can log the client out - ee.$on(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() { - var privateNamespace = getPrivateNamespace(namespaces); - log((LOGOUT_EVENT_NAME + " event triggered")); - // disconnect(nsps, opts.serverType) - // we need to issue error to all the namespace onError handler - triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME); - // rebind all of the handler to the fake one - log(("logout from " + privateNamespace)); - - clearMainEmitEvt(ee, privateNamespace); - // we need to issue one more call to the server before we disconnect - // now this is a catch 22, here we are not suppose to do anything platform specific - // so that should fire before trigger this event - // clear out the nsp - nsps[privateNamespace] = null; - // add a NOT LOGIN error if call - notLoginWsHandler(privateNamespace, ee, opts); - }); -}; - -/** - * A Event handler placeholder when it's not connect to any nsp - * @param {string} namespace nsp - * @param {object} ee EventEmitter - * @param {object} opts configuration - * @return {void} - */ -var disconnectedHandler = function (namespace, ee, opts) { - var log = opts.log; - ee.$only( - createEvt(namespace, EMIT_EVT), - function disconnectedHandlerCallback(resolverName, args) { - log("[disconnectedHandler] hijack the ws call", namespace, resolverName, args); - var error = { - message: DISCONNECTED_ERROR_MSG - }; - ee.$call(createEvt(namespace, resolverName, ON_ERROR_FN_NAME), [ error ]); - // also trigger the result handler, but wrap inside the error key - ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error: error }]); - } - ); -}; - - -/** - * The disconnect event handler, now we log the client out from everything - * @TODO now we are another problem they disconnect, how to reconnect - * @param {object} nsps the available nsp(s) - * @param {array} namespaces available namespace - * @param {object} ee eventEmitter - * @param {object} opts configuration - * @return {void} - */ -var disconnectHandler = function (nsps, namespaces, ee, opts) { - var log = opts.log; - ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() { - triggerNamespacesOnError(ee, namespaces, DISCONNECT_EVENT_NAME); - namespaces.forEach( function (namespace) { - log(("disconnect from " + namespace)); - - clearMainEmitEvt(ee, namespace); - nsps[namespace] = null; - disconnectedHandler(namespace, ee, opts); - }); - }); -}; - /** * centralize all the comm in one place * @param {object} opts configuration @@ -7877,10 +7780,10 @@ function clientEventHandler$1(opts, nspMap, ee, bindSocketEventHandler, nsps) { // logout event handler if (hasPrivate) { log("Has private and add logoutEvtHandler"); - logoutEvtHandler(nsps, namespaces, ee, opts); + // logoutEvtHandler(nsps, namespaces, ee, opts) } // finally the disconnect event handlers - disconnectHandler(nsps, namespaces, ee, opts); + // disconnectHandler(nsps, namespaces, ee, opts) } // this will be part of the init client sequence @@ -10138,6 +10041,8 @@ var createNspAction$1 = function(opts, nspMap, token) { var namespaces = nspMap.namespaces; log("createNspAction", 'publicNamespace', publicNamespace, 'namespaces', namespaces); + // reverse the namespaces because it got stuck for some reason + // const reverseNamespaces = namespaces.reverse() if (opts.enableAuth) { return chainPromises( namespaces.map(function (namespace, i) { @@ -10521,12 +10426,12 @@ var errorTypeHandler = function (ee, namespace, resolverName, json) { * @param {object} ws the WebSocket instance * @return {void} */ -var logoutEventHandler = function (ee, ws) { - // @TODO we need find a way to get the userdata - ws.send(createIntercomPayload(LOGOUT_EVENT_NAME$1)); +var logoutEventListener = function (ee, ws) { // listen to the LOGOUT_EVENT_NAME when this is a private nsp ee.$on(LOGOUT_EVENT_NAME$1, function closeEvtHandler() { try { + // @TODO we need find a way to get the userdata + ws.send(createIntercomPayload(LOGOUT_EVENT_NAME$1)); log('terminate ws connection'); ws.terminate(); } catch(e) { @@ -10636,8 +10541,9 @@ function bindSocketEventHandler(namespace, ws, ee, isPrivate, opts) { }; if (isPrivate) { - logoutEventHandler(ee, ws); + logoutEventListener(ee, ws); } + } // actually binding the event client to the socket client diff --git a/packages/@jsonql/ws/main.js.map b/packages/@jsonql/ws/main.js.map index 279d3c87..dc94d863 100644 --- a/packages/@jsonql/ws/main.js.map +++ b/packages/@jsonql/ws/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","sources":["node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arrayMap.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_objectToString.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isObjectLike.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseSlice.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseFindIndex.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseIsNaN.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_strictIndexOf.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_asciiToArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_hasUnicode.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_unicodeToArray.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/number.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/string.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/boolean.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/any.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/constants.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/combine.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/array.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_overArg.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/validator.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_listCacheClear.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/eq.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_stackDelete.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_stackGet.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_stackHas.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isObject.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_toSource.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_getValue.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_hashDelete.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_isKeyable.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_createBaseFor.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_copyArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_isPrototype.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isLength.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/stubFalse.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseUnary.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_safeGet.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseTimes.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_isIndex.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_nativeKeysIn.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/identity.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_apply.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/constant.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_shortOut.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_setCacheAdd.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_setCacheHas.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arraySome.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_cacheHas.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_mapToArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_setToArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arrayPush.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arrayFilter.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/stubArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_matchesStrictComparable.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseHasIn.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseProperty.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/negate.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseFindKey.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/is-in-array.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/enum-error.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/type-error.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/checker-error.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/run-validation.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/check-options-async.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/construct-config.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/index.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/index.js","../../ws-client-core/src/utils/get-log-fn.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/constants.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/store.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/utils.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/suspend.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/store-service.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/event-service.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/index.js","../../ws-client-core/src/utils/get-event-emitter.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/generic.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/contract.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/timestamp.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/params-api.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/namespace.js","../../ws-client-core/src/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-send-method.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/setup-intercom.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/share/create-nsp-clients.js","../../ws-client-core/src/share/trigger-namespaces-on-error.js","../../ws-client-core/src/share/client-event-handler.js","../../ws-client-core/src/share/intercom-methods.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.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/login-event-handler.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/create-nsp/bind-socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.js","src/node-ws-client.js"],"sourcesContent":["export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * 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","// 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","/**\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","// 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","// 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","// 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","/**\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","/** 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","// 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","// 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","// 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// generic placeholder function\nexport const nil = () => false\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/**\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","// 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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log))\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/**\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 createNamespaceErrorHandler(client, opts, ee, nspGroup) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the clientitself\n objDefineProps(client, ON_ERROR_FN_NAME, 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 opts,\n ee\n ]\n}\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 createOnReadyHandler(client, opts, ee) {\n return [\n objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n} from './resolver-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 generator(opts, nspMap, ee) {\n\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n ]\n if (opts.enableAuth) {\n args.push(\n createAuthMethods\n )\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n args.push(setupFinalStep)\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n\n return fn(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 { generator } from './core'\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} frameworkSocketEngine \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(frameworkSocketEngine, config) {\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`jsonql-ws-core-client init error`, err)\n })\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} frameworkSocketEngine 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(frameworkSocketEngine, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(opts => wsClientCoreAction(frameworkSocketEngine, opts))\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}","// 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\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, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event handler 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 */\nconst notLoginWsHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n log('[notLoginHandler] 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 handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nconst getPrivateNamespace = (namespaces) => (\n namespaces.length > 1 ? namespaces[0] : false\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 */\nconst logoutEvtHandler = (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(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() {\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 handler\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the handler 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 notLoginWsHandler(privateNamespace, ee, opts)\n })\n}\n\n/**\n * A Event handler 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 */\nconst disconnectedHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedHandlerCallback(resolverName, args) {\n log(`[disconnectedHandler] 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 handler, 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 handler, 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 */\nconst disconnectHandler = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() {\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 disconnectedHandler(namespace, ee, opts)\n })\n })\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts \n * @param {object} ee Event Emitter instance\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 clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) {\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 let isPrivate = false\n let hasPrivate = false\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run in order here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace\n if (!hasPrivate) {\n hasPrivate = isPrivate\n }\n // log(namespace, ' --> nsps --> ', nsps[namespace])\n if (nsps[namespace]) {\n\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n Reflect.apply(bindSocketEventHandler, null, args)\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 notLoginWsHandler(namespace, ee, opts)\n }\n })\n // logout event handler \n if (hasPrivate) {\n log(`Has private and add logoutEvtHandler`)\n logoutEvtHandler(nsps, namespaces, ee, opts)\n }\n // finally the disconnect event handlers\n disconnectHandler(nsps, namespaces, ee, opts) \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 * 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 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 json = toJson(payload)\n const result = extractWsPayload(json)\n if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\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 createInitPing, \n extractPingResult, \n createIntercomPayload \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 // the csrf cause all kinds of problem so we abandoned it for now\n return resolver(ws)\n /*\n // terminate the client \n ws.terminate()\n // return the new one with csrf header\n // @BUG too quick and kill the socket?\n setTimeout(() => {\n const newWs = new WebSocket(url, Object.assign(wsOptions, header)) \n resolver(newWs) \n }, 50)\n */\n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\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 \n log(`nspClient: \\n${_url}\\n`, wsOptions)\n\n return new Promise((resolver, rejecter) => { \n \n const unconfirmClient = new WebSocket(_url, wsOptions)\n \n resolver(unconfirmClient)\n\n // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\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\n log(`nspAuthClient: \\n${_url}\\n`, wsOptions)\n\n return new Promise((resolver, rejecter) => {\n const unconfirmClient = new WebSocket(_url, wsOptions)\n \n resolver(unconfirmClient)\n\n // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\n }\n}\n\nexport { initWebSocketClient }","/** 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","// @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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError,\n createIntercomPayload\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nconst logoutEventHandler = (ee, ws) => {\n // @TODO we need find a way to get the userdata \n ws.send(createIntercomPayload(LOGOUT_EVENT_NAME))\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() {\n try {\n log('terminate ws connection')\n ws.terminate()\n } catch(e) {\n console.error('ws.terminate error', e)\n }\n })\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\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventHandler(ee, ws)\n }\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventHandler } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // arguments for clientEventHandler\n const args = [opts, nspMap, ee, bindSocketEventHandler]\n // now create the nsps\n // const { namespaces } = nspMap\n const { token } = opts\n\n return createNspAction(opts, nspMap, token)\n .then(nsps => {\n args.push(nsps)\n Reflect.apply(clientEventHandler, null, args)\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n }) \n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\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 * @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 opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log) \n // @1.0.7 remove later once everything fixed \n \n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ No newline at end of file +{"version":3,"file":"main.js","sources":["node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arrayMap.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_objectToString.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isObjectLike.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseSlice.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseFindIndex.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseIsNaN.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_strictIndexOf.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_asciiToArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_hasUnicode.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_unicodeToArray.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/number.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/string.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/boolean.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/any.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/constants.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/combine.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/array.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_overArg.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/validator.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_listCacheClear.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/eq.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_stackDelete.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_stackGet.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_stackHas.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isObject.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_toSource.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_getValue.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_hashDelete.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_isKeyable.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_createBaseFor.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_copyArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_isPrototype.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isLength.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/stubFalse.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseUnary.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_safeGet.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseTimes.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_isIndex.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_nativeKeysIn.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/identity.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_apply.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/constant.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_shortOut.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_setCacheAdd.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_setCacheHas.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arraySome.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_cacheHas.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_mapToArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_setToArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arrayPush.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arrayFilter.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/stubArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_matchesStrictComparable.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseHasIn.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseProperty.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/negate.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseFindKey.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/is-in-array.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/enum-error.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/type-error.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/checker-error.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/run-validation.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/check-options-async.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/construct-config.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/index.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/index.js","../../ws-client-core/src/utils/get-log-fn.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/constants.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/store.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/utils.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/suspend.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/store-service.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/event-service.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/index.js","../../ws-client-core/src/utils/get-event-emitter.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/generic.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/contract.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/timestamp.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/params-api.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/namespace.js","../../ws-client-core/src/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-send-method.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/setup-intercom.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/share/create-nsp-clients.js","../../ws-client-core/src/share/trigger-namespaces-on-error.js","../../ws-client-core/src/share/client-event-handler.js","../../ws-client-core/src/share/intercom-methods.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.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/login-event-handler.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/create-nsp/bind-socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.js","src/node-ws-client.js"],"sourcesContent":["export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * 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","// 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","/**\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","// 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","// 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","// 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","/**\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","/** 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","// 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","// 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","// 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// generic placeholder function\nexport const nil = () => false\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/**\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","// 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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log))\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/**\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 createNamespaceErrorHandler(client, opts, ee, nspGroup) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the clientitself\n objDefineProps(client, ON_ERROR_FN_NAME, 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 opts,\n ee\n ]\n}\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 createOnReadyHandler(client, opts, ee) {\n return [\n objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n} from './resolver-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 generator(opts, nspMap, ee) {\n\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n ]\n if (opts.enableAuth) {\n args.push(\n createAuthMethods\n )\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n args.push(setupFinalStep)\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n\n return fn(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 { generator } from './core'\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} frameworkSocketEngine \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(frameworkSocketEngine, config) {\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`jsonql-ws-core-client init error`, err)\n })\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} frameworkSocketEngine 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(frameworkSocketEngine, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(opts => wsClientCoreAction(frameworkSocketEngine, opts))\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}","// 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\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, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event handler 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 */\nconst notLoginWsHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n log('[notLoginHandler] 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 handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nconst getPrivateNamespace = (namespaces) => (\n namespaces.length > 1 ? namespaces[0] : false\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 */\nconst logoutEvtHandler = (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(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() {\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 handler\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the handler 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 notLoginWsHandler(privateNamespace, ee, opts)\n })\n}\n\n/**\n * A Event handler 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 */\nconst disconnectedHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedHandlerCallback(resolverName, args) {\n log(`[disconnectedHandler] 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 handler, 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 handler, 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 */\nconst disconnectHandler = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() {\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 disconnectedHandler(namespace, ee, opts)\n })\n })\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts \n * @param {object} ee Event Emitter instance\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 clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) {\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 let isPrivate = false\n let hasPrivate = false\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run in order here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace\n if (!hasPrivate) {\n hasPrivate = isPrivate\n }\n // log(namespace, ' --> nsps --> ', nsps[namespace])\n if (nsps[namespace]) {\n\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n Reflect.apply(bindSocketEventHandler, null, args)\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 notLoginWsHandler(namespace, ee, opts)\n }\n })\n // logout event handler \n if (hasPrivate) {\n log(`Has private and add logoutEvtHandler`)\n // logoutEvtHandler(nsps, namespaces, ee, opts)\n }\n // finally the disconnect event handlers\n // disconnectHandler(nsps, namespaces, ee, opts) \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 * 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 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 json = toJson(payload)\n const result = extractWsPayload(json)\n if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\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 createInitPing, \n extractPingResult, \n createIntercomPayload \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 // the csrf cause all kinds of problem so we abandoned it for now\n return resolver(ws)\n /*\n // terminate the client \n ws.terminate()\n // return the new one with csrf header\n // @BUG too quick and kill the socket?\n setTimeout(() => {\n const newWs = new WebSocket(url, Object.assign(wsOptions, header)) \n resolver(newWs) \n }, 50)\n */\n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\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 \n log(`nspClient: \\n${_url}\\n`, wsOptions)\n\n return new Promise((resolver, rejecter) => { \n \n const unconfirmClient = new WebSocket(_url, wsOptions)\n \n resolver(unconfirmClient)\n\n // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\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\n log(`nspAuthClient: \\n${_url}\\n`, wsOptions)\n\n return new Promise((resolver, rejecter) => {\n const unconfirmClient = new WebSocket(_url, wsOptions)\n \n resolver(unconfirmClient)\n\n // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\n }\n}\n\nexport { initWebSocketClient }","/** 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","// @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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError,\n createIntercomPayload\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nconst logoutEventListener = (ee, ws) => {\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_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}\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\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventListener(ee, ws)\n }\n\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventHandler } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // arguments for clientEventHandler\n const args = [opts, nspMap, ee, bindSocketEventHandler]\n // now create the nsps\n // const { namespaces } = nspMap\n const { token } = opts\n\n return createNspAction(opts, nspMap, token)\n .then(nsps => {\n args.push(nsps)\n Reflect.apply(clientEventHandler, null, args)\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n }) \n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\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 * @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 opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log) \n // @1.0.7 remove later once everything fixed \n \n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ No newline at end of file diff --git a/packages/@jsonql/ws/src/core/create-nsp/bind-socket-event-handler.js b/packages/@jsonql/ws/src/core/create-nsp/bind-socket-event-handler.js index 4aaea8f3..b1ac42bf 100644 --- a/packages/@jsonql/ws/src/core/create-nsp/bind-socket-event-handler.js +++ b/packages/@jsonql/ws/src/core/create-nsp/bind-socket-event-handler.js @@ -48,12 +48,12 @@ const errorTypeHandler = (ee, namespace, resolverName, json) => { * @param {object} ws the WebSocket instance * @return {void} */ -const logoutEventHandler = (ee, ws) => { - // @TODO we need find a way to get the userdata - ws.send(createIntercomPayload(LOGOUT_EVENT_NAME)) +const logoutEventListener = (ee, ws) => { // listen to the LOGOUT_EVENT_NAME when this is a private nsp ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() { try { + // @TODO we need find a way to get the userdata + ws.send(createIntercomPayload(LOGOUT_EVENT_NAME)) log('terminate ws connection') ws.terminate() } catch(e) { @@ -162,6 +162,7 @@ export function bindSocketEventHandler(namespace, ws, ee, isPrivate, opts) { } if (isPrivate) { - logoutEventHandler(ee, ws) + logoutEventListener(ee, ws) } + } diff --git a/packages/@jsonql/ws/src/core/create-nsp/create-nsp-action.js b/packages/@jsonql/ws/src/core/create-nsp/create-nsp-action.js index ad261ea3..58933a86 100644 --- a/packages/@jsonql/ws/src/core/create-nsp/create-nsp-action.js +++ b/packages/@jsonql/ws/src/core/create-nsp/create-nsp-action.js @@ -21,6 +21,8 @@ const createNspAction = function(opts, nspMap, token) { let { publicNamespace, namespaces } = nspMap log(`createNspAction`, 'publicNamespace', publicNamespace, 'namespaces', namespaces) + // reverse the namespaces because it got stuck for some reason + // const reverseNamespaces = namespaces.reverse() if (opts.enableAuth) { return chainPromises( namespaces.map((namespace, i) => { diff --git a/packages/ws-client-core/src/share/client-event-handler.js b/packages/ws-client-core/src/share/client-event-handler.js index a9b94300..d85a10f0 100644 --- a/packages/ws-client-core/src/share/client-event-handler.js +++ b/packages/ws-client-core/src/share/client-event-handler.js @@ -45,84 +45,7 @@ const getPrivateNamespace = (namespaces) => ( namespaces.length > 1 ? namespaces[0] : false ) -/** - * Only when there is a private namespace then we bind to this event - * @param {object} nsps the available nsp(s) - * @param {array} namespaces available namespace - * @param {object} ee eventEmitter - * @param {object} opts configuration - * @return {void} - */ -const logoutEvtHandler = (nsps, namespaces, ee, opts) => { - const { log } = opts - // this will be available regardless enableAuth - // because the server can log the client out - ee.$on(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() { - const privateNamespace = getPrivateNamespace(namespaces) - log(`${LOGOUT_EVENT_NAME} event triggered`) - // disconnect(nsps, opts.serverType) - // we need to issue error to all the namespace onError handler - triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME) - // rebind all of the handler to the fake one - log(`logout from ${privateNamespace}`) - - clearMainEmitEvt(ee, privateNamespace) - // we need to issue one more call to the server before we disconnect - // now this is a catch 22, here we are not suppose to do anything platform specific - // so that should fire before trigger this event - // clear out the nsp - nsps[privateNamespace] = null - // add a NOT LOGIN error if call - notLoginWsHandler(privateNamespace, ee, opts) - }) -} - -/** - * A Event handler placeholder when it's not connect to any nsp - * @param {string} namespace nsp - * @param {object} ee EventEmitter - * @param {object} opts configuration - * @return {void} - */ -const disconnectedHandler = (namespace, ee, opts) => { - const { log } = opts - ee.$only( - createEvt(namespace, EMIT_EVT), - function disconnectedHandlerCallback(resolverName, args) { - log(`[disconnectedHandler] hijack the ws call`, namespace, resolverName, args) - const error = { - message: DISCONNECTED_ERROR_MSG - } - ee.$call(createEvt(namespace, resolverName, ON_ERROR_FN_NAME), [ error ]) - // also trigger the result handler, but wrap inside the error key - ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }]) - } - ) -} - -/** - * The disconnect event handler, now we log the client out from everything - * @TODO now we are another problem they disconnect, how to reconnect - * @param {object} nsps the available nsp(s) - * @param {array} namespaces available namespace - * @param {object} ee eventEmitter - * @param {object} opts configuration - * @return {void} - */ -const disconnectHandler = (nsps, namespaces, ee, opts) => { - const { log } = opts - ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() { - triggerNamespacesOnError(ee, namespaces, DISCONNECT_EVENT_NAME) - namespaces.forEach( namespace => { - log(`disconnect from ${namespace}`) - - clearMainEmitEvt(ee, namespace) - nsps[namespace] = null - disconnectedHandler(namespace, ee, opts) - }) - }) -} /** * centralize all the comm in one place @@ -173,8 +96,8 @@ export function clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsp // logout event handler if (hasPrivate) { log(`Has private and add logoutEvtHandler`) - logoutEvtHandler(nsps, namespaces, ee, opts) + // logoutEvtHandler(nsps, namespaces, ee, opts) } // finally the disconnect event handlers - disconnectHandler(nsps, namespaces, ee, opts) + // disconnectHandler(nsps, namespaces, ee, opts) } diff --git a/packages/ws-client-core/src/share/event-listerners.js b/packages/ws-client-core/src/share/event-listerners.js new file mode 100644 index 00000000..4dc867d1 --- /dev/null +++ b/packages/ws-client-core/src/share/event-listerners.js @@ -0,0 +1,80 @@ +// NOT IN USE AT THE MOMENT JUST KEEP IT HERE FOR THE TIME BEING + +/** + * Only when there is a private namespace then we bind to this event + * @param {object} nsps the available nsp(s) + * @param {array} namespaces available namespace + * @param {object} ee eventEmitter + * @param {object} opts configuration + * @return {void} + */ +const logoutEvtHandler = (nsps, namespaces, ee, opts) => { + const { log } = opts + // this will be available regardless enableAuth + // because the server can log the client out + ee.$on(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() { + const privateNamespace = getPrivateNamespace(namespaces) + log(`${LOGOUT_EVENT_NAME} event triggered`) + // disconnect(nsps, opts.serverType) + // we need to issue error to all the namespace onError handler + triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME) + // rebind all of the handler to the fake one + log(`logout from ${privateNamespace}`) + + clearMainEmitEvt(ee, privateNamespace) + // we need to issue one more call to the server before we disconnect + // now this is a catch 22, here we are not suppose to do anything platform specific + // so that should fire before trigger this event + // clear out the nsp + nsps[privateNamespace] = null + // add a NOT LOGIN error if call + notLoginWsHandler(privateNamespace, ee, opts) + }) +} + +/** + * A Event handler placeholder when it's not connect to any nsp + * @param {string} namespace nsp + * @param {object} ee EventEmitter + * @param {object} opts configuration + * @return {void} + */ +const disconnectedHandler = (namespace, ee, opts) => { + const { log } = opts + ee.$only( + createEvt(namespace, EMIT_EVT), + function disconnectedHandlerCallback(resolverName, args) { + log(`[disconnectedHandler] hijack the ws call`, namespace, resolverName, args) + const error = { + message: DISCONNECTED_ERROR_MSG + } + ee.$call(createEvt(namespace, resolverName, ON_ERROR_FN_NAME), [ error ]) + // also trigger the result handler, but wrap inside the error key + ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }]) + } + ) +} + + +/** + * The disconnect event handler, now we log the client out from everything + * @TODO now we are another problem they disconnect, how to reconnect + * @param {object} nsps the available nsp(s) + * @param {array} namespaces available namespace + * @param {object} ee eventEmitter + * @param {object} opts configuration + * @return {void} + */ +const disconnectHandler = (nsps, namespaces, ee, opts) => { + const { log } = opts + ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() { + triggerNamespacesOnError(ee, namespaces, DISCONNECT_EVENT_NAME) + namespaces.forEach( namespace => { + log(`disconnect from ${namespace}`) + + clearMainEmitEvt(ee, namespace) + nsps[namespace] = null + disconnectedHandler(namespace, ee, opts) + }) + }) +} \ No newline at end of file -- Gitee From e73d8a7ceba770be861f7f6b84eaa44370e67298 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 14:08:07 +0800 Subject: [PATCH 22/66] rename bunch of folders --- packages/utils/module.js | 4 +++- packages/utils/package.json | 2 +- packages/utils/src/namespace.js | 8 ++++++++ packages/ws-client-core/README.md | 10 ++++++++++ packages/ws-client-core/src/api.js | 10 +++++----- .../src/{core => callers}/action-call.js | 0 .../generator.js => callers/callers-generator.js} | 2 +- .../src/{core => callers}/cb/callback-handler.js | 0 .../src/{core => callers}/cb/setup-callback-api.js | 0 .../ws-client-core/src/{core => callers}/index.js | 6 +++--- .../src/{core => callers}/resolver-methods.js | 0 .../src/{core => callers}/respond-handler.js | 0 .../src/{core => callers}/setup-auth-methods.js | 0 .../src/{core => callers}/setup-final-step.js | 0 .../src/{core => callers}/setup-intercom.js | 0 .../src/{core => callers}/setup-resolver.js | 0 .../src/{core => callers}/setup-send-method.js | 0 .../client-event-listerner.js} | 11 +---------- .../src/{share => listener}/create-nsp-clients.js | 0 .../src/{share => listener}/event-listerners.js | 0 .../src/{share => listener}/intercom-methods.js | 2 +- .../trigger-namespaces-on-error.js | 0 packages/ws-client-core/tests/tbd.test.js | 2 +- 23 files changed, 34 insertions(+), 23 deletions(-) rename packages/ws-client-core/src/{core => callers}/action-call.js (100%) rename packages/ws-client-core/src/{core/generator.js => callers/callers-generator.js} (95%) rename packages/ws-client-core/src/{core => callers}/cb/callback-handler.js (100%) rename packages/ws-client-core/src/{core => callers}/cb/setup-callback-api.js (100%) rename packages/ws-client-core/src/{core => callers}/index.js (30%) rename packages/ws-client-core/src/{core => callers}/resolver-methods.js (100%) rename packages/ws-client-core/src/{core => callers}/respond-handler.js (100%) rename packages/ws-client-core/src/{core => callers}/setup-auth-methods.js (100%) rename packages/ws-client-core/src/{core => callers}/setup-final-step.js (100%) rename packages/ws-client-core/src/{core => callers}/setup-intercom.js (100%) rename packages/ws-client-core/src/{core => callers}/setup-resolver.js (100%) rename packages/ws-client-core/src/{core => callers}/setup-send-method.js (100%) rename packages/ws-client-core/src/{share/client-event-handler.js => listener/client-event-listerner.js} (92%) rename packages/ws-client-core/src/{share => listener}/create-nsp-clients.js (100%) rename packages/ws-client-core/src/{share => listener}/event-listerners.js (100%) rename packages/ws-client-core/src/{share => listener}/intercom-methods.js (97%) rename packages/ws-client-core/src/{share => listener}/trigger-namespaces-on-error.js (100%) diff --git a/packages/utils/module.js b/packages/utils/module.js index 9bdd7f24..2f62cf53 100644 --- a/packages/utils/module.js +++ b/packages/utils/module.js @@ -65,7 +65,8 @@ import { groupByNamespace, getNamespaceInOrder, getNamespace, - getNspInfoByConfig + getNspInfoByConfig, + getPrivateNamespace } from './src/namespace' import { isRegExp, @@ -138,6 +139,7 @@ export { getNamespace, getNspInfoByConfig, getResolverFromPayload, + getPrivateNamespace, // 1.0.6 isRegExp, getRegex, diff --git a/packages/utils/package.json b/packages/utils/package.json index 2cedae58..2ed3a34e 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-utils", - "version": "1.2.1", + "version": "1.2.2", "description": "This is a jsonql dependency module, not for generate use.", "main": "main.js", "module": "index.js", diff --git a/packages/utils/src/namespace.js b/packages/utils/src/namespace.js index a063b4ec..e1fce661 100644 --- a/packages/utils/src/namespace.js +++ b/packages/utils/src/namespace.js @@ -103,6 +103,14 @@ export function getNamespace(config) { return [ base ] } +/** + * get the private namespace + * @param {array} namespaces array + * @return {*} string on success + */ +export function getPrivateNamespace(namespaces) { + return namespaces.length > 1 ? namespaces[0] : false +} /** * Got a problem with a contract that is public only the groupByNamespace is wrong diff --git a/packages/ws-client-core/README.md b/packages/ws-client-core/README.md index 6e33db26..5bc45e93 100644 --- a/packages/ws-client-core/README.md +++ b/packages/ws-client-core/README.md @@ -11,6 +11,16 @@ Please check the following - [@jsonql/socketio](https://npmjs.com/package/@jsonql/socketio) for [Socket.io](https://npmjs.com/package/socketio) client / server - ~~@jsonql/primus for Primus client / server~~ (planning stage) +## Architecture + +The entire sequence of create a Web Socket client: + +check configuration --> capture contract --> generate resolvers (event callers) --> connect to socket server --> create event listeners + +Therefore the upper level part of the client, for example `WebSocket` only provide the framework sepecific +interface. Then this package will do the rest. + + ## Create combine client 2020-03-13 diff --git a/packages/ws-client-core/src/api.js b/packages/ws-client-core/src/api.js index c5ef2359..7848973b 100644 --- a/packages/ws-client-core/src/api.js +++ b/packages/ws-client-core/src/api.js @@ -2,7 +2,7 @@ // The goal is to create a generic method that will able to handle // any kind of clients // import { injectToFn } from 'jsonql-utils' -import { generator } from './core' +import { callersGenerator } from './callers' import { checkConfiguration, postCheckInjectOpts, @@ -12,18 +12,18 @@ import { /** * 0.5.0 we break up the wsClientCore in two parts one without the config check - * @param {function} frameworkSocketEngine + * @param {function} socketClientListerner * @param {object} config the already checked config */ -export function wsClientCoreAction(frameworkSocketEngine, config) { +export function wsClientCoreAction(socketClientListerner, config) { return postCheckInjectOpts(config) // the following two moved to wsPostConfig .then(createRequiredParams) .then( - ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee) + ({opts, nspMap, ee}) => callersGenerator(opts, nspMap, ee) ) .then( - ({opts, nspMap, ee}) => generator(opts, nspMap, ee) + ({opts, nspMap, ee}) => socketClientListerner(opts, nspMap, ee) ) .catch(err => { console.error(`jsonql-ws-core-client init error`, err) diff --git a/packages/ws-client-core/src/core/action-call.js b/packages/ws-client-core/src/callers/action-call.js similarity index 100% rename from packages/ws-client-core/src/core/action-call.js rename to packages/ws-client-core/src/callers/action-call.js diff --git a/packages/ws-client-core/src/core/generator.js b/packages/ws-client-core/src/callers/callers-generator.js similarity index 95% rename from packages/ws-client-core/src/core/generator.js rename to packages/ws-client-core/src/callers/callers-generator.js index e71fec52..7884676b 100644 --- a/packages/ws-client-core/src/core/generator.js +++ b/packages/ws-client-core/src/callers/callers-generator.js @@ -22,7 +22,7 @@ import { * @return {object} of resolvers * @public */ -export function generator(opts, nspMap, ee) { +export function callersGenerator(opts, nspMap, ee) { let args = [ generateResolvers, diff --git a/packages/ws-client-core/src/core/cb/callback-handler.js b/packages/ws-client-core/src/callers/cb/callback-handler.js similarity index 100% rename from packages/ws-client-core/src/core/cb/callback-handler.js rename to packages/ws-client-core/src/callers/cb/callback-handler.js diff --git a/packages/ws-client-core/src/core/cb/setup-callback-api.js b/packages/ws-client-core/src/callers/cb/setup-callback-api.js similarity index 100% rename from packages/ws-client-core/src/core/cb/setup-callback-api.js rename to packages/ws-client-core/src/callers/cb/setup-callback-api.js diff --git a/packages/ws-client-core/src/core/index.js b/packages/ws-client-core/src/callers/index.js similarity index 30% rename from packages/ws-client-core/src/core/index.js rename to packages/ws-client-core/src/callers/index.js index a6faf947..f2b12064 100644 --- a/packages/ws-client-core/src/core/index.js +++ b/packages/ws-client-core/src/callers/index.js @@ -1,5 +1,5 @@ // just doing the import export thing here -import { generator } from './generator' - -export { generator } +import { callersGenerator } from './callers-generator' +// just rename it +export { callersGenerator } diff --git a/packages/ws-client-core/src/core/resolver-methods.js b/packages/ws-client-core/src/callers/resolver-methods.js similarity index 100% rename from packages/ws-client-core/src/core/resolver-methods.js rename to packages/ws-client-core/src/callers/resolver-methods.js diff --git a/packages/ws-client-core/src/core/respond-handler.js b/packages/ws-client-core/src/callers/respond-handler.js similarity index 100% rename from packages/ws-client-core/src/core/respond-handler.js rename to packages/ws-client-core/src/callers/respond-handler.js diff --git a/packages/ws-client-core/src/core/setup-auth-methods.js b/packages/ws-client-core/src/callers/setup-auth-methods.js similarity index 100% rename from packages/ws-client-core/src/core/setup-auth-methods.js rename to packages/ws-client-core/src/callers/setup-auth-methods.js diff --git a/packages/ws-client-core/src/core/setup-final-step.js b/packages/ws-client-core/src/callers/setup-final-step.js similarity index 100% rename from packages/ws-client-core/src/core/setup-final-step.js rename to packages/ws-client-core/src/callers/setup-final-step.js diff --git a/packages/ws-client-core/src/core/setup-intercom.js b/packages/ws-client-core/src/callers/setup-intercom.js similarity index 100% rename from packages/ws-client-core/src/core/setup-intercom.js rename to packages/ws-client-core/src/callers/setup-intercom.js diff --git a/packages/ws-client-core/src/core/setup-resolver.js b/packages/ws-client-core/src/callers/setup-resolver.js similarity index 100% rename from packages/ws-client-core/src/core/setup-resolver.js rename to packages/ws-client-core/src/callers/setup-resolver.js diff --git a/packages/ws-client-core/src/core/setup-send-method.js b/packages/ws-client-core/src/callers/setup-send-method.js similarity index 100% rename from packages/ws-client-core/src/core/setup-send-method.js rename to packages/ws-client-core/src/callers/setup-send-method.js diff --git a/packages/ws-client-core/src/share/client-event-handler.js b/packages/ws-client-core/src/listener/client-event-listerner.js similarity index 92% rename from packages/ws-client-core/src/share/client-event-handler.js rename to packages/ws-client-core/src/listener/client-event-listerner.js index d85a10f0..d89a666a 100644 --- a/packages/ws-client-core/src/share/client-event-handler.js +++ b/packages/ws-client-core/src/listener/client-event-listerner.js @@ -36,15 +36,6 @@ const notLoginWsHandler = (namespace, ee, opts) => { ) } -/** - * get the private namespace - * @param {array} namespaces array - * @return {*} string on success - */ -const getPrivateNamespace = (namespaces) => ( - namespaces.length > 1 ? namespaces[0] : false -) - /** @@ -56,7 +47,7 @@ const getPrivateNamespace = (namespaces) => ( * @param {object} nsps namespaced nsp * @return {void} nothing */ -export function clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) { +export function clientEventListerner(opts, nspMap, ee, bindSocketEventHandler, nsps) { // since all these params already in the opts const { log } = opts const { namespaces } = nspMap diff --git a/packages/ws-client-core/src/share/create-nsp-clients.js b/packages/ws-client-core/src/listener/create-nsp-clients.js similarity index 100% rename from packages/ws-client-core/src/share/create-nsp-clients.js rename to packages/ws-client-core/src/listener/create-nsp-clients.js diff --git a/packages/ws-client-core/src/share/event-listerners.js b/packages/ws-client-core/src/listener/event-listerners.js similarity index 100% rename from packages/ws-client-core/src/share/event-listerners.js rename to packages/ws-client-core/src/listener/event-listerners.js diff --git a/packages/ws-client-core/src/share/intercom-methods.js b/packages/ws-client-core/src/listener/intercom-methods.js similarity index 97% rename from packages/ws-client-core/src/share/intercom-methods.js rename to packages/ws-client-core/src/listener/intercom-methods.js index 58258430..6ea85d49 100644 --- a/packages/ws-client-core/src/share/intercom-methods.js +++ b/packages/ws-client-core/src/listener/intercom-methods.js @@ -19,7 +19,7 @@ import { } from 'jsonql-utils/module' import { JsonqlError -} from 'jsonql-errors' +} from '../callers/node_modules/jsonql-errors' const CSRF_HEADER_NOT_EXIST_ERR = 'CSRF header is not in the received payload' /** diff --git a/packages/ws-client-core/src/share/trigger-namespaces-on-error.js b/packages/ws-client-core/src/listener/trigger-namespaces-on-error.js similarity index 100% rename from packages/ws-client-core/src/share/trigger-namespaces-on-error.js rename to packages/ws-client-core/src/listener/trigger-namespaces-on-error.js diff --git a/packages/ws-client-core/tests/tbd.test.js b/packages/ws-client-core/tests/tbd.test.js index 9d417d65..0f38ef36 100644 --- a/packages/ws-client-core/tests/tbd.test.js +++ b/packages/ws-client-core/tests/tbd.test.js @@ -41,7 +41,7 @@ test.cb(`We should able to get a list of event register via the eventEmitter`, t } }) -test.cb(`Should able to listsen to the onLogin callback`, t => { +test.cb(`Should able to listen to the onLogin callback`, t => { t.plan(1) -- Gitee From f1944567b0a38a302837cd1d9a716d06475e5cdc Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 14:08:36 +0800 Subject: [PATCH 23/66] jsonql-utils 1.2.2 --- packages/utils/browser.js | 2 +- packages/utils/main.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/utils/browser.js b/packages/utils/browser.js index 7acc54d7..fad23181 100644 --- a/packages/utils/browser.js +++ b/packages/utils/browser.js @@ -1,2 +1,2 @@ -!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t=t||self).jsonqlUtils={})}(this,(function(t){"use strict";var r=Array.isArray,e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},n="object"==typeof e&&e&&e.Object===Object&&e,o="object"==typeof self&&self&&self.Object===Object&&self,u=n||o||Function("return this")(),i=u.Symbol,a=Object.prototype,c=a.hasOwnProperty,f=a.toString,s=i?i.toStringTag:void 0;var l=Object.prototype.toString;var p=i?i.toStringTag:void 0;function v(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":p&&p in Object(t)?function(t){var r=c.call(t,s),e=t[s];try{t[s]=void 0;var n=!0}catch(t){}var o=f.call(t);return n&&(r?t[s]=e:delete t[s]),o}(t):function(t){return l.call(t)}(t)}var d,y,h=(d=Object.getPrototypeOf,y=Object,function(t){return d(y(t))});function _(t){return null!=t&&"object"==typeof t}var g=Function.prototype,b=Object.prototype,j=g.toString,m=b.hasOwnProperty,w=j.call(Object);function O(t){if(!_(t)||"[object Object]"!=v(t))return!1;var r=h(t);if(null===r)return!0;var e=m.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&j.call(e)==w}var S=i?i.prototype:void 0,P=S?S.toString:void 0;function N(t){if("string"==typeof t)return t;if(r(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var u=Array(o);++n-1;);return e}(o,u),function(t,r){for(var e=t.length;e--&&E(r,t[e],0)>-1;);return e}(o,u)+1).join("")}var I=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return r(t)?t:[t]},L=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},V=function(t,r){try{var e=Object.keys(t);return I(e,r)}catch(t){return!1}},W=function(t){return L("string"==typeof t?t:JSON.stringify(t))},H=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function Z(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var X=Array.prototype.splice;function Y(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},Y.prototype.set=function(t,r){var e=this.__data__,n=Z(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function rt(t){if(!tt(t))return!1;var r=v(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var et,nt=u["__core-js_shared__"],ot=(et=/[^.]+$/.exec(nt&&nt.keys&&nt.keys.IE_PROTO||""))?"Symbol(src)_1."+et:"";var ut=Function.prototype.toString;var it=/^\[object .+?Constructor\]$/,at=Function.prototype,ct=Object.prototype,ft=at.toString,st=ct.hasOwnProperty,lt=RegExp("^"+ft.call(st).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pt(t){return!(!tt(t)||function(t){return!!ot&&ot in t}(t))&&(rt(t)?lt:it).test(function(t){if(null!=t){try{return ut.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function vt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pt(e)?e:void 0}var dt=vt(u,"Map"),yt=vt(Object,"create");var ht=Object.prototype.hasOwnProperty;var _t=Object.prototype.hasOwnProperty;function gt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Gt(t.length)&&!rt(t)}var It="object"==typeof t&&t&&!t.nodeType&&t,Qt=It&&"object"==typeof module&&module&&!module.nodeType&&module,Lt=Qt&&Qt.exports===It?u.Buffer:void 0,Vt=(Lt?Lt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Ht="object"==typeof t&&t&&!t.nodeType&&t,Kt=Ht&&"object"==typeof module&&module&&!module.nodeType&&module,Zt=Kt&&Kt.exports===Ht&&n.process,Xt=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Zt&&Zt.binding&&Zt.binding("util")}catch(t){}}(),Yt=Xt&&Xt.isTypedArray,tr=Yt?function(t){return function(r){return t(r)}}(Yt):function(t){return _(t)&&Gt(t.length)&&!!Wt[v(t)]};function rr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var er=Object.prototype.hasOwnProperty;function nr(t,r,e){var n=t[r];er.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||Ot(t,r,e)}var or=/^(?:0|[1-9]\d*)$/;function ur(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&or.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(_r);function jr(t,r){return br(function(t,r,e){return r=hr(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,u=hr(n.length-r,0),i=Array(u);++o1?r[n-1]:void 0,u=n>2?r[2]:void 0;for(o=mr.length>3&&"function"==typeof o?(n--,o):void 0,u&&function(t,r,e){if(!tt(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ur(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],u)&&(o=n<3?void 0:o,n=1),t=Object(t);++e0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},t.chainProcessPromises=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return t.then((function(t){return r(t)}))}),Reflect.apply(t,null,e))}},t.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):wr(t,e)}))}))}),Promise.resolve(!1===r?[]:O(r)?r:{}))},t.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("acknowledge_reply",t,r,e)},t.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},t.createMutation=Ur,t.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Ur(t,r,e,n))},t.createQuery=qr,t.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},t.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("emit_reply",t,r,e)},t.createWsReply=Wr,t.dasherize=function(t){return $(t).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},t.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ar("Unknown "+r+" to extract argument from!")}},t.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Pr(e,r);return n}catch(t){throw new Pr(e,t)}},t.extractSocketPart=Tr,t.extractWsPayload=function(t,r){void 0===r&&(r=H);try{var e,n=W(t);if(!1!==(e=Hr(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ar("payload can not decoded",t)}catch(t){return r("error",t)}},t.formatPayload=Jr,t.getCallMethod=function(t){switch(!0){case t===Sr[0]:return"query";case t===Sr[1]:return"mutation";default:return!1}},t.getConfigValue=function(t,r){return r&&O(r)&&t in r?r[t]:void 0},t.getLogger=function(t){var r=[t];return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];try{window&&window.JSONQL_DEBUG&&Reflect.apply(console.info,console,r.concat(t))}catch(t){}}},t.getMutationFromArgs=Gr,t.getMutationFromPayload=function(t){var r=Dr(t,Gr);if(!1!==r)return r;throw new Nr("[getMutationArgs] Payload is malformed!",t)},t.getNamespace=Qr,t.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},t.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Qr(t),o=e?Ir(r):function(t,r){var e,n={};for(var o in t){var u=t[o];n[o]=u}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},t.getQueryFromArgs=Br,t.getQueryFromPayload=function(t){var r=Dr(t,Br);if(!1!==r)return r;throw new Nr("[getQueryArgs] Payload is malformed!",t)},t.getRegex=function(t){switch(!0){case!0===Lr(t):return t;case!0===kr(t):return new RegExp(t);default:return!1}},t.getResolverFromPayload=Mr,t.groupByNamespace=Ir,t.inArray=I,t.injectToFn=function(t,r,e,n){void 0===n&&(n=!1);var o=Or(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t},t.isContract=function(t){return!!function(t){return O(t)&&(V(t,"query")||V(t,"mutation")||V(t,"socket"))}(t)&&t},t.isFunc=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},t.isJsonqlErrorObj=$r,t.isNotEmpty=function(t){return void 0!==t&&!1!==t&&null!==t&&""!==$(t)},t.isObjectHasKey=V,t.isRegExp=Lr,t.isWsReply=Hr,t.logger=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];try{window&&window.DEBUG&&Reflect.apply(console.log,console,t)}catch(t){}},t.nil=H,t.objDefineProps=function(t,r,e,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,r)&&Object.defineProperty(t,r,{set:e,get:null===n?function(){return null}:n}),t},t.objHasProp=Or,t.packError=function(t,r,e,n){var o;void 0===r&&(r="JsonqlError"),void 0===e&&(e=0),void 0===n&&(n="");var u={detail:t,className:r,statusCode:e,message:n};return JSON.stringify(((o={}).error=$r(t)||u,o.TS=[Er()],o))},t.packResult=function(t,e){void 0===e&&(e=!1);var n={};return n.data=t,e&&r(e)&&(e.push(Er()),n.TS=e),JSON.stringify(n)},t.parseJson=L,t.resultHandler=function(t){return V(t,"data")&&!V(t,"error")?t.data:t},t.timestamp=Er,t.toArray=Q,t.toJson=W,t.toPayload=Rr,t.urlParams=xr,Object.defineProperty(t,"__esModule",{value:!0})})); +!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t=t||self).jsonqlUtils={})}(this,(function(t){"use strict";var r=Array.isArray,e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},n="object"==typeof e&&e&&e.Object===Object&&e,o="object"==typeof self&&self&&self.Object===Object&&self,u=n||o||Function("return this")(),i=u.Symbol,a=Object.prototype,c=a.hasOwnProperty,f=a.toString,s=i?i.toStringTag:void 0;var l=Object.prototype.toString;var p=i?i.toStringTag:void 0;function v(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":p&&p in Object(t)?function(t){var r=c.call(t,s),e=t[s];try{t[s]=void 0;var n=!0}catch(t){}var o=f.call(t);return n&&(r?t[s]=e:delete t[s]),o}(t):function(t){return l.call(t)}(t)}var d,y,h=(d=Object.getPrototypeOf,y=Object,function(t){return d(y(t))});function g(t){return null!=t&&"object"==typeof t}var _=Function.prototype,b=Object.prototype,j=_.toString,m=b.hasOwnProperty,w=j.call(Object);function O(t){if(!g(t)||"[object Object]"!=v(t))return!1;var r=h(t);if(null===r)return!0;var e=m.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&j.call(e)==w}var S=i?i.prototype:void 0,P=S?S.toString:void 0;function N(t){if("string"==typeof t)return t;if(r(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var u=Array(o);++n-1;);return e}(o,u),function(t,r){for(var e=t.length;e--&&E(r,t[e],0)>-1;);return e}(o,u)+1).join("")}var I=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return r(t)?t:[t]},L=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},V=function(t,r){try{var e=Object.keys(t);return I(e,r)}catch(t){return!1}},W=function(t){return L("string"==typeof t?t:JSON.stringify(t))},H=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function Z(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var X=Array.prototype.splice;function Y(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},Y.prototype.set=function(t,r){var e=this.__data__,n=Z(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function rt(t){if(!tt(t))return!1;var r=v(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var et,nt=u["__core-js_shared__"],ot=(et=/[^.]+$/.exec(nt&&nt.keys&&nt.keys.IE_PROTO||""))?"Symbol(src)_1."+et:"";var ut=Function.prototype.toString;var it=/^\[object .+?Constructor\]$/,at=Function.prototype,ct=Object.prototype,ft=at.toString,st=ct.hasOwnProperty,lt=RegExp("^"+ft.call(st).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pt(t){return!(!tt(t)||function(t){return!!ot&&ot in t}(t))&&(rt(t)?lt:it).test(function(t){if(null!=t){try{return ut.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function vt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pt(e)?e:void 0}var dt=vt(u,"Map"),yt=vt(Object,"create");var ht=Object.prototype.hasOwnProperty;var gt=Object.prototype.hasOwnProperty;function _t(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Gt(t.length)&&!rt(t)}var It="object"==typeof t&&t&&!t.nodeType&&t,Qt=It&&"object"==typeof module&&module&&!module.nodeType&&module,Lt=Qt&&Qt.exports===It?u.Buffer:void 0,Vt=(Lt?Lt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Ht="object"==typeof t&&t&&!t.nodeType&&t,Kt=Ht&&"object"==typeof module&&module&&!module.nodeType&&module,Zt=Kt&&Kt.exports===Ht&&n.process,Xt=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Zt&&Zt.binding&&Zt.binding("util")}catch(t){}}(),Yt=Xt&&Xt.isTypedArray,tr=Yt?function(t){return function(r){return t(r)}}(Yt):function(t){return g(t)&&Gt(t.length)&&!!Wt[v(t)]};function rr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var er=Object.prototype.hasOwnProperty;function nr(t,r,e){var n=t[r];er.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||Ot(t,r,e)}var or=/^(?:0|[1-9]\d*)$/;function ur(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&or.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(gr);function jr(t,r){return br(function(t,r,e){return r=hr(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,u=hr(n.length-r,0),i=Array(u);++o1?r[n-1]:void 0,u=n>2?r[2]:void 0;for(o=mr.length>3&&"function"==typeof o?(n--,o):void 0,u&&function(t,r,e){if(!tt(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ur(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],u)&&(o=n<3?void 0:o,n=1),t=Object(t);++e0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},t.chainProcessPromises=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return t.then((function(t){return r(t)}))}),Reflect.apply(t,null,e))}},t.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):wr(t,e)}))}))}),Promise.resolve(!1===r?[]:O(r)?r:{}))},t.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("acknowledge_reply",t,r,e)},t.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},t.createMutation=Ur,t.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Ur(t,r,e,n))},t.createQuery=qr,t.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},t.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("emit_reply",t,r,e)},t.createWsReply=Wr,t.dasherize=function(t){return $(t).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},t.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ar("Unknown "+r+" to extract argument from!")}},t.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Pr(e,r);return n}catch(t){throw new Pr(e,t)}},t.extractSocketPart=Tr,t.extractWsPayload=function(t,r){void 0===r&&(r=H);try{var e,n=W(t);if(!1!==(e=Hr(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ar("payload can not decoded",t)}catch(t){return r("error",t)}},t.formatPayload=Jr,t.getCallMethod=function(t){switch(!0){case t===Sr[0]:return"query";case t===Sr[1]:return"mutation";default:return!1}},t.getConfigValue=function(t,r){return r&&O(r)&&t in r?r[t]:void 0},t.getLogger=function(t){var r=[t];return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];try{window&&window.JSONQL_DEBUG&&Reflect.apply(console.info,console,r.concat(t))}catch(t){}}},t.getMutationFromArgs=Gr,t.getMutationFromPayload=function(t){var r=Dr(t,Gr);if(!1!==r)return r;throw new Nr("[getMutationArgs] Payload is malformed!",t)},t.getNamespace=Qr,t.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},t.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Qr(t),o=e?Ir(r):function(t,r){var e,n={};for(var o in t){var u=t[o];n[o]=u}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},t.getPrivateNamespace=function(t){return t.length>1&&t[0]},t.getQueryFromArgs=Br,t.getQueryFromPayload=function(t){var r=Dr(t,Br);if(!1!==r)return r;throw new Nr("[getQueryArgs] Payload is malformed!",t)},t.getRegex=function(t){switch(!0){case!0===Lr(t):return t;case!0===kr(t):return new RegExp(t);default:return!1}},t.getResolverFromPayload=Mr,t.groupByNamespace=Ir,t.inArray=I,t.injectToFn=function(t,r,e,n){void 0===n&&(n=!1);var o=Or(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t},t.isContract=function(t){return!!function(t){return O(t)&&(V(t,"query")||V(t,"mutation")||V(t,"socket"))}(t)&&t},t.isFunc=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},t.isJsonqlErrorObj=$r,t.isNotEmpty=function(t){return void 0!==t&&!1!==t&&null!==t&&""!==$(t)},t.isObjectHasKey=V,t.isRegExp=Lr,t.isWsReply=Hr,t.logger=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];try{window&&window.DEBUG&&Reflect.apply(console.log,console,t)}catch(t){}},t.nil=H,t.objDefineProps=function(t,r,e,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,r)&&Object.defineProperty(t,r,{set:e,get:null===n?function(){return null}:n}),t},t.objHasProp=Or,t.packError=function(t,r,e,n){var o;void 0===r&&(r="JsonqlError"),void 0===e&&(e=0),void 0===n&&(n="");var u={detail:t,className:r,statusCode:e,message:n};return JSON.stringify(((o={}).error=$r(t)||u,o.TS=[Er()],o))},t.packResult=function(t,e){void 0===e&&(e=!1);var n={};return n.data=t,e&&r(e)&&(e.push(Er()),n.TS=e),JSON.stringify(n)},t.parseJson=L,t.resultHandler=function(t){return V(t,"data")&&!V(t,"error")?t.data:t},t.timestamp=Er,t.toArray=Q,t.toJson=W,t.toPayload=Rr,t.urlParams=xr,Object.defineProperty(t,"__esModule",{value:!0})})); //# sourceMappingURL=browser.js.map diff --git a/packages/utils/main.js b/packages/utils/main.js index 9b7579dc..262c4d52 100644 --- a/packages/utils/main.js +++ b/packages/utils/main.js @@ -1,2 +1,2 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t,r=(t=require("fs"))&&"object"==typeof t&&"default"in t?t.default:t,e=require("path"),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,u="object"==typeof self&&self&&self.Object===Object&&self,a=i||u||Function("return this")(),f=a.Symbol,s=Object.prototype,c=s.hasOwnProperty,h=s.toString,p=f?f.toStringTag:void 0;var l=Object.prototype.toString;var g=f?f.toStringTag:void 0;function y(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":g&&g in Object(t)?function(t){var r=c.call(t,p),e=t[p];try{t[p]=void 0;var n=!0}catch(t){}var o=h.call(t);return n&&(r?t[p]=e:delete t[p]),o}(t):function(t){return l.call(t)}(t)}var v,d,_=(v=Object.getPrototypeOf,d=Object,function(t){return v(d(t))});function b(t){return null!=t&&"object"==typeof t}var w=Function.prototype,m=Object.prototype,A=w.toString,E=m.hasOwnProperty,x=A.call(Object);function j(t){if(!b(t)||"[object Object]"!=y(t))return!1;var r=_(t);if(null===r)return!0;var e=E.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&A.call(e)==x}var P=f?f.prototype:void 0,R=P?P.toString:void 0;function O(t){if("string"==typeof t)return t;if(n(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var i=Array(o);++n-1;);return e}(o,i),function(t,r){for(var e=t.length;e--&&U(r,t[e],0)>-1;);return e}(o,i)+1).join("")}var G=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return n(t)?t:[t]},V=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},H=function(t,r){try{var e=Object.keys(t);return G(e,r)}catch(t){return!1}},W=function(t){return V("string"==typeof t?t:JSON.stringify(t))},Z=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function X(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var tt=Array.prototype.splice;function rt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},rt.prototype.set=function(t,r){var e=this.__data__,n=X(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function nt(t){if(!et(t))return!1;var r=y(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var ot,it=a["__core-js_shared__"],ut=(ot=/[^.]+$/.exec(it&&it.keys&&it.keys.IE_PROTO||""))?"Symbol(src)_1."+ot:"";var at=Function.prototype.toString;var ft=/^\[object .+?Constructor\]$/,st=Function.prototype,ct=Object.prototype,ht=st.toString,pt=ct.hasOwnProperty,lt=RegExp("^"+ht.call(pt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function gt(t){return!(!et(t)||function(t){return!!ut&&ut in t}(t))&&(nt(t)?lt:ft).test(function(t){if(null!=t){try{return at.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function yt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return gt(e)?e:void 0}var vt=yt(a,"Map"),dt=yt(Object,"create");var _t=Object.prototype.hasOwnProperty;var bt=Object.prototype.hasOwnProperty;function wt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Jt(t.length)&&!nt(t)}var Gt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Qt=Gt&&"object"==typeof module&&module&&!module.nodeType&&module,Vt=Qt&&Qt.exports===Gt?a.Buffer:void 0,Ht=(Vt?Vt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Zt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Kt=Zt&&"object"==typeof module&&module&&!module.nodeType&&module,Xt=Kt&&Kt.exports===Zt&&i.process,tr=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Xt&&Xt.binding&&Xt.binding("util")}catch(t){}}(),rr=tr&&tr.isTypedArray,er=rr?function(t){return function(r){return t(r)}}(rr):function(t){return b(t)&&Jt(t.length)&&!!Wt[y(t)]};function nr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var or=Object.prototype.hasOwnProperty;function ir(t,r,e){var n=t[r];or.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||jt(t,r,e)}var ur=/^(?:0|[1-9]\d*)$/;function ar(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&ur.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(br);function Ar(t,r){return mr(function(t,r,e){return r=_r(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,i=_r(n.length-r,0),u=Array(i);++o1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=Er.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!et(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ar(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e>18&63]+re[o>>12&63]+re[o>>6&63]+re[63&o]);return i.join("")}function ae(t){var r;oe||ie();for(var e=t.length,n=e%3,o="",i=[],u=0,a=e-n;ua?a:u+16383));return 1===n?(r=t[e-1],o+=re[r>>2],o+=re[r<<4&63],o+="=="):2===n&&(r=(t[e-2]<<8)+t[e-1],o+=re[r>>10],o+=re[r>>4&63],o+=re[r<<2&63],o+="="),i.push(o),i.join("")}function fe(t,r,e,n,o){var i,u,a=8*o-n-1,f=(1<>1,c=-7,h=e?o-1:0,p=e?-1:1,l=t[r+h];for(h+=p,i=l&(1<<-c)-1,l>>=-c,c+=a;c>0;i=256*i+t[r+h],h+=p,c-=8);for(u=i&(1<<-c)-1,i>>=-c,c+=n;c>0;u=256*u+t[r+h],h+=p,c-=8);if(0===i)i=1-s;else{if(i===f)return u?NaN:1/0*(l?-1:1);u+=Math.pow(2,n),i-=s}return(l?-1:1)*u*Math.pow(2,i-n)}function se(t,r,e,n,o,i){var u,a,f,s=8*i-o-1,c=(1<>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,l=n?0:i-1,g=n?1:-1,y=r<0||0===r&&1/r<0?1:0;for(r=Math.abs(r),isNaN(r)||r===1/0?(a=isNaN(r)?1:0,u=c):(u=Math.floor(Math.log(r)/Math.LN2),r*(f=Math.pow(2,-u))<1&&(u--,f*=2),(r+=u+h>=1?p/f:p*Math.pow(2,1-h))*f>=2&&(u++,f/=2),u+h>=c?(a=0,u=c):u+h>=1?(a=(r*f-1)*Math.pow(2,o),u+=h):(a=r*Math.pow(2,h-1)*Math.pow(2,o),u=0));o>=8;t[e+l]=255&a,l+=g,a/=256,o-=8);for(u=u<0;t[e+l]=255&u,l+=g,u/=256,s-=8);t[e+l-g]|=128*y}var ce={}.toString,he=Array.isArray||function(t){return"[object Array]"==ce.call(t)};function pe(){return ge.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function le(t,r){if(pe()=pe())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+pe().toString(16)+" bytes");return 0|t}function we(t){return!(null==t||!t._isBuffer)}function me(t,r){if(we(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var e=t.length;if(0===e)return 0;for(var n=!1;;)switch(r){case"ascii":case"latin1":case"binary":return e;case"utf8":case"utf-8":case void 0:return Qe(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*e;case"hex":return e>>>1;case"base64":return Ve(t).length;default:if(n)return Qe(t).length;r=(""+r).toLowerCase(),n=!0}}function Ae(t,r,e){var n=!1;if((void 0===r||r<0)&&(r=0),r>this.length)return"";if((void 0===e||e>this.length)&&(e=this.length),e<=0)return"";if((e>>>=0)<=(r>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return Ye(this,r,e);case"utf8":case"utf-8":return Ne(this,r,e);case"ascii":return Ie(this,r,e);case"latin1":case"binary":return Ce(this,r,e);case"base64":return Be(this,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Me(this,r,e);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function Ee(t,r,e){var n=t[r];t[r]=t[e],t[e]=n}function xe(t,r,e,n,o){if(0===t.length)return-1;if("string"==typeof e?(n=e,e=0):e>2147483647?e=2147483647:e<-2147483648&&(e=-2147483648),e=+e,isNaN(e)&&(e=o?0:t.length-1),e<0&&(e=t.length+e),e>=t.length){if(o)return-1;e=t.length-1}else if(e<0){if(!o)return-1;e=0}if("string"==typeof r&&(r=ge.from(r,n)),we(r))return 0===r.length?-1:je(t,r,e,n,o);if("number"==typeof r)return r&=255,ge.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,r,e):Uint8Array.prototype.lastIndexOf.call(t,r,e):je(t,[r],e,n,o);throw new TypeError("val must be string, number or Buffer")}function je(t,r,e,n,o){var i,u=1,a=t.length,f=r.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||r.length<2)return-1;u=2,a/=2,f/=2,e/=2}function s(t,r){return 1===u?t[r]:t.readUInt16BE(r*u)}if(o){var c=-1;for(i=e;ia&&(e=a-f),i=e;i>=0;i--){for(var h=!0,p=0;po&&(n=o):n=o;var i=r.length;if(i%2!=0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var u=0;u>8,o=e%256,i.push(o),i.push(n);return i}(r,t.length-e),t,e,n)}function Be(t,r,e){return 0===r&&e===t.length?ae(t):ae(t.slice(r,e))}function Ne(t,r,e){e=Math.min(t.length,e);for(var n=[],o=r;o239?4:s>223?3:s>191?2:1;if(o+h<=e)switch(h){case 1:s<128&&(c=s);break;case 2:128==(192&(i=t[o+1]))&&(f=(31&s)<<6|63&i)>127&&(c=f);break;case 3:i=t[o+1],u=t[o+2],128==(192&i)&&128==(192&u)&&(f=(15&s)<<12|(63&i)<<6|63&u)>2047&&(f<55296||f>57343)&&(c=f);break;case 4:i=t[o+1],u=t[o+2],a=t[o+3],128==(192&i)&&128==(192&u)&&128==(192&a)&&(f=(15&s)<<18|(63&i)<<12|(63&u)<<6|63&a)>65535&&f<1114112&&(c=f)}null===c?(c=65533,h=1):c>65535&&(c-=65536,n.push(c>>>10&1023|55296),c=56320|1023&c),n.push(c),o+=h}return function(t){var r=t.length;if(r<=4096)return String.fromCharCode.apply(String,t);var e="",n=0;for(;n0&&(t=this.toString("hex",0,50).match(/.{2}/g).join(" "),this.length>50&&(t+=" ... ")),""},ge.prototype.compare=function(t,r,e,n,o){if(!we(t))throw new TypeError("Argument must be a Buffer");if(void 0===r&&(r=0),void 0===e&&(e=t?t.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),r<0||e>t.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&r>=e)return 0;if(n>=o)return-1;if(r>=e)return 1;if(this===t)return 0;for(var i=(o>>>=0)-(n>>>=0),u=(e>>>=0)-(r>>>=0),a=Math.min(i,u),f=this.slice(n,o),s=t.slice(r,e),c=0;co)&&(e=o),t.length>0&&(e<0||r<0)||r>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return Pe(this,t,r,e);case"utf8":case"utf-8":return Re(this,t,r,e);case"ascii":return Oe(this,t,r,e);case"latin1":case"binary":return Te(this,t,r,e);case"base64":return Se(this,t,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Ue(this,t,r,e);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},ge.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Ie(t,r,e){var n="";e=Math.min(t.length,e);for(var o=r;on)&&(e=n);for(var o="",i=r;ie)throw new RangeError("Trying to access beyond buffer length")}function De(t,r,e,n,o,i){if(!we(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(r>o||rt.length)throw new RangeError("Index out of range")}function Le(t,r,e,n){r<0&&(r=65535+r+1);for(var o=0,i=Math.min(t.length-e,2);o>>8*(n?o:1-o)}function ze(t,r,e,n){r<0&&(r=4294967295+r+1);for(var o=0,i=Math.min(t.length-e,4);o>>8*(n?o:3-o)&255}function Fe(t,r,e,n,o,i){if(e+n>t.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function qe(t,r,e,n,o){return o||Fe(t,0,e,4),se(t,r,e,n,23,4),e+4}function Je(t,r,e,n,o){return o||Fe(t,0,e,8),se(t,r,e,n,52,8),e+8}ge.prototype.slice=function(t,r){var e,n=this.length;if((t=~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),(r=void 0===r?n:~~r)<0?(r+=n)<0&&(r=0):r>n&&(r=n),r0&&(o*=256);)n+=this[t+--r]*o;return n},ge.prototype.readUInt8=function(t,r){return r||ke(t,1,this.length),this[t]},ge.prototype.readUInt16LE=function(t,r){return r||ke(t,2,this.length),this[t]|this[t+1]<<8},ge.prototype.readUInt16BE=function(t,r){return r||ke(t,2,this.length),this[t]<<8|this[t+1]},ge.prototype.readUInt32LE=function(t,r){return r||ke(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},ge.prototype.readUInt32BE=function(t,r){return r||ke(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},ge.prototype.readIntLE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=this[t],o=1,i=0;++i=(o*=128)&&(n-=Math.pow(2,8*r)),n},ge.prototype.readIntBE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=r,o=1,i=this[t+--n];n>0&&(o*=256);)i+=this[t+--n]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*r)),i},ge.prototype.readInt8=function(t,r){return r||ke(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},ge.prototype.readInt16LE=function(t,r){r||ke(t,2,this.length);var e=this[t]|this[t+1]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt16BE=function(t,r){r||ke(t,2,this.length);var e=this[t+1]|this[t]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt32LE=function(t,r){return r||ke(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},ge.prototype.readInt32BE=function(t,r){return r||ke(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},ge.prototype.readFloatLE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!0,23,4)},ge.prototype.readFloatBE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!1,23,4)},ge.prototype.readDoubleLE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!0,52,8)},ge.prototype.readDoubleBE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!1,52,8)},ge.prototype.writeUIntLE=function(t,r,e,n){(t=+t,r|=0,e|=0,n)||De(this,t,r,e,Math.pow(2,8*e)-1,0);var o=1,i=0;for(this[r]=255&t;++i=0&&(i*=256);)this[r+o]=t/i&255;return r+e},ge.prototype.writeUInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,255,0),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[r]=255&t,r+1},ge.prototype.writeUInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeUInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeUInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r+3]=t>>>24,this[r+2]=t>>>16,this[r+1]=t>>>8,this[r]=255&t):ze(this,t,r,!0),r+4},ge.prototype.writeUInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeIntLE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=0,u=1,a=0;for(this[r]=255&t;++i>0)-a&255;return r+e},ge.prototype.writeIntBE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=e-1,u=1,a=0;for(this[r+i]=255&t;--i>=0&&(u*=256);)t<0&&0===a&&0!==this[r+i+1]&&(a=1),this[r+i]=(t/u>>0)-a&255;return r+e},ge.prototype.writeInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,127,-128),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[r]=255&t,r+1},ge.prototype.writeInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8,this[r+2]=t>>>16,this[r+3]=t>>>24):ze(this,t,r,!0),r+4},ge.prototype.writeInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeFloatLE=function(t,r,e){return qe(this,t,r,!0,e)},ge.prototype.writeFloatBE=function(t,r,e){return qe(this,t,r,!1,e)},ge.prototype.writeDoubleLE=function(t,r,e){return Je(this,t,r,!0,e)},ge.prototype.writeDoubleBE=function(t,r,e){return Je(this,t,r,!1,e)},ge.prototype.copy=function(t,r,e,n){if(e||(e=0),n||0===n||(n=this.length),r>=t.length&&(r=t.length),r||(r=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-r=0;--o)t[o+r]=this[o+e];else if(i<1e3||!ge.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,e=void 0===e?this.length:e>>>0,t||(t=0),"number"==typeof t)for(i=r;i55295&&e<57344){if(!o){if(e>56319){(r-=3)>-1&&i.push(239,191,189);continue}if(u+1===n){(r-=3)>-1&&i.push(239,191,189);continue}o=e;continue}if(e<56320){(r-=3)>-1&&i.push(239,191,189),o=e;continue}e=65536+(o-55296<<10|e-56320)}else o&&(r-=3)>-1&&i.push(239,191,189);if(o=null,e<128){if((r-=1)<0)break;i.push(e)}else if(e<2048){if((r-=2)<0)break;i.push(e>>6|192,63&e|128)}else if(e<65536){if((r-=3)<0)break;i.push(e>>12|224,e>>6&63|128,63&e|128)}else{if(!(e<1114112))throw new Error("Invalid code point");if((r-=4)<0)break;i.push(e>>18|240,e>>12&63|128,e>>6&63|128,63&e|128)}}return i}function Ve(t){return function(t){var r,e,n,o,i,u;oe||ie();var a=t.length;if(a%4>0)throw new Error("Invalid string. Length must be a multiple of 4");i="="===t[a-2]?2:"="===t[a-1]?1:0,u=new ne(3*a/4-i),n=i>0?a-4:a;var f=0;for(r=0,e=0;r>16&255,u[f++]=o>>8&255,u[f++]=255&o;return 2===i?(o=ee[t.charCodeAt(r)]<<2|ee[t.charCodeAt(r+1)]>>4,u[f++]=255&o):1===i&&(o=ee[t.charCodeAt(r)]<<10|ee[t.charCodeAt(r+1)]<<4|ee[t.charCodeAt(r+2)]>>2,u[f++]=o>>8&255,u[f++]=255&o),u}(function(t){if((t=function(t){if(t.trim)return t.trim();return t.replace(/^\s+|\s+$/g,"")}(t).replace($e,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function He(t,r,e,n){for(var o=0;o=r.length||o>=t.length);++o)r[o+e]=t[o];return o}function We(t){return null!=t&&(!!t._isBuffer||Ze(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&Ze(t.slice(0,0))}(t))}function Ze(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}var Ke=function(t,r){if(r instanceof Error){var e={};return Object.getOwnPropertyNames(r).forEach((function(t){e[t]=r[t]})),e}return r};var Xe=function(t,r){try{var e=t.headers.accept.split(",");return r?e.filter((function(t){return t===r})):e}catch(t){return[]}},tn=function(t,r){return!!Xe(t,r).length},rn=function(t,r){return t.path===r.jsonqlPath};exports.VERSION="1.2.1",exports.buff=function(t,r){return void 0===r&&(r="base64"),We(t)?t:new ge.from(t,r)},exports.cacheBurst=Yr,exports.cacheBurstUrl=function(t){return Cr(t,Yr())},exports.chainFns=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},exports.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):xr(t,e)}))}))}),Promise.resolve(!1===r?[]:j(r)?r:{}))},exports.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("acknowledge_reply",t,r,e)},exports.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},exports.createMutation=Jr,exports.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Jr(t,r,e,n))},exports.createQuery=qr,exports.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},exports.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("emit_reply",t,r,e)},exports.createWsReply=Xr,exports.dasherize=Ir,exports.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ur("Unknown "+r+" to extract argument from!")}},exports.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Tr(e,r);return n}catch(t){throw new Tr(e,t)}},exports.extractSocketPart=Br,exports.extractWsPayload=function(t,r){void 0===r&&(r=Z);try{var e,n=W(t);if(!1!==(e=te(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ur("payload can not decoded",t)}catch(t){return r("error",t)}},exports.findFromContract=function(t,e,n){return!!(n[t]&&n[t][e]&&n[t][e].file&&r.existsSync(n[t][e].file))&&n[t][e].file},exports.formatPayload=Lr,exports.getCallMethod=function(t){switch(!0){case t===Rr[0]:return"query";case t===Rr[1]:return"mutation";default:return!1}},exports.getConfigValue=function(t,r){return r&&j(r)&&t in r?r[t]:void 0},exports.getDocLen=function(t){return ge.byteLength(t,"utf8")},exports.getMutationFromArgs=Qr,exports.getMutationFromPayload=function(t){var r=Gr(t,Qr);if(!1!==r)return r;throw new Sr("[getMutationArgs] Payload is malformed!",t)},exports.getNamespace=Wr,exports.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},exports.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Wr(t),o=e?Hr(r):function(t,r){var e,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},exports.getPathToFn=function(t,n,o){var i=o.resolverDir,u=Ir(t),a=[];o.contract&&o.contract[n]&&o.contract[n].path&&a.push(o.contract[n].path),a.push(e.join(i,n,u,[Or,Pr].join("."))),a.push(e.join(i,n,[u,Pr].join(".")));for(var f=a.length,s=0;s=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var i=Array(o);++n-1;);return e}(o,i),function(t,r){for(var e=t.length;e--&&U(r,t[e],0)>-1;);return e}(o,i)+1).join("")}var G=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return n(t)?t:[t]},V=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},H=function(t,r){try{var e=Object.keys(t);return G(e,r)}catch(t){return!1}},W=function(t){return V("string"==typeof t?t:JSON.stringify(t))},Z=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function X(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var tt=Array.prototype.splice;function rt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},rt.prototype.set=function(t,r){var e=this.__data__,n=X(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function nt(t){if(!et(t))return!1;var r=y(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var ot,it=a["__core-js_shared__"],ut=(ot=/[^.]+$/.exec(it&&it.keys&&it.keys.IE_PROTO||""))?"Symbol(src)_1."+ot:"";var at=Function.prototype.toString;var ft=/^\[object .+?Constructor\]$/,st=Function.prototype,ct=Object.prototype,ht=st.toString,pt=ct.hasOwnProperty,lt=RegExp("^"+ht.call(pt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function gt(t){return!(!et(t)||function(t){return!!ut&&ut in t}(t))&&(nt(t)?lt:ft).test(function(t){if(null!=t){try{return at.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function yt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return gt(e)?e:void 0}var vt=yt(a,"Map"),dt=yt(Object,"create");var _t=Object.prototype.hasOwnProperty;var bt=Object.prototype.hasOwnProperty;function wt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Jt(t.length)&&!nt(t)}var Gt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Qt=Gt&&"object"==typeof module&&module&&!module.nodeType&&module,Vt=Qt&&Qt.exports===Gt?a.Buffer:void 0,Ht=(Vt?Vt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Zt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Kt=Zt&&"object"==typeof module&&module&&!module.nodeType&&module,Xt=Kt&&Kt.exports===Zt&&i.process,tr=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Xt&&Xt.binding&&Xt.binding("util")}catch(t){}}(),rr=tr&&tr.isTypedArray,er=rr?function(t){return function(r){return t(r)}}(rr):function(t){return b(t)&&Jt(t.length)&&!!Wt[y(t)]};function nr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var or=Object.prototype.hasOwnProperty;function ir(t,r,e){var n=t[r];or.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||jt(t,r,e)}var ur=/^(?:0|[1-9]\d*)$/;function ar(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&ur.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(br);function Ar(t,r){return mr(function(t,r,e){return r=_r(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,i=_r(n.length-r,0),u=Array(i);++o1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=Er.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!et(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ar(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e>18&63]+re[o>>12&63]+re[o>>6&63]+re[63&o]);return i.join("")}function ae(t){var r;oe||ie();for(var e=t.length,n=e%3,o="",i=[],u=0,a=e-n;ua?a:u+16383));return 1===n?(r=t[e-1],o+=re[r>>2],o+=re[r<<4&63],o+="=="):2===n&&(r=(t[e-2]<<8)+t[e-1],o+=re[r>>10],o+=re[r>>4&63],o+=re[r<<2&63],o+="="),i.push(o),i.join("")}function fe(t,r,e,n,o){var i,u,a=8*o-n-1,f=(1<>1,c=-7,h=e?o-1:0,p=e?-1:1,l=t[r+h];for(h+=p,i=l&(1<<-c)-1,l>>=-c,c+=a;c>0;i=256*i+t[r+h],h+=p,c-=8);for(u=i&(1<<-c)-1,i>>=-c,c+=n;c>0;u=256*u+t[r+h],h+=p,c-=8);if(0===i)i=1-s;else{if(i===f)return u?NaN:1/0*(l?-1:1);u+=Math.pow(2,n),i-=s}return(l?-1:1)*u*Math.pow(2,i-n)}function se(t,r,e,n,o,i){var u,a,f,s=8*i-o-1,c=(1<>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,l=n?0:i-1,g=n?1:-1,y=r<0||0===r&&1/r<0?1:0;for(r=Math.abs(r),isNaN(r)||r===1/0?(a=isNaN(r)?1:0,u=c):(u=Math.floor(Math.log(r)/Math.LN2),r*(f=Math.pow(2,-u))<1&&(u--,f*=2),(r+=u+h>=1?p/f:p*Math.pow(2,1-h))*f>=2&&(u++,f/=2),u+h>=c?(a=0,u=c):u+h>=1?(a=(r*f-1)*Math.pow(2,o),u+=h):(a=r*Math.pow(2,h-1)*Math.pow(2,o),u=0));o>=8;t[e+l]=255&a,l+=g,a/=256,o-=8);for(u=u<0;t[e+l]=255&u,l+=g,u/=256,s-=8);t[e+l-g]|=128*y}var ce={}.toString,he=Array.isArray||function(t){return"[object Array]"==ce.call(t)};function pe(){return ge.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function le(t,r){if(pe()=pe())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+pe().toString(16)+" bytes");return 0|t}function we(t){return!(null==t||!t._isBuffer)}function me(t,r){if(we(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var e=t.length;if(0===e)return 0;for(var n=!1;;)switch(r){case"ascii":case"latin1":case"binary":return e;case"utf8":case"utf-8":case void 0:return Qe(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*e;case"hex":return e>>>1;case"base64":return Ve(t).length;default:if(n)return Qe(t).length;r=(""+r).toLowerCase(),n=!0}}function Ae(t,r,e){var n=!1;if((void 0===r||r<0)&&(r=0),r>this.length)return"";if((void 0===e||e>this.length)&&(e=this.length),e<=0)return"";if((e>>>=0)<=(r>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return Ye(this,r,e);case"utf8":case"utf-8":return Ne(this,r,e);case"ascii":return Ie(this,r,e);case"latin1":case"binary":return Ce(this,r,e);case"base64":return Be(this,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Me(this,r,e);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function Ee(t,r,e){var n=t[r];t[r]=t[e],t[e]=n}function xe(t,r,e,n,o){if(0===t.length)return-1;if("string"==typeof e?(n=e,e=0):e>2147483647?e=2147483647:e<-2147483648&&(e=-2147483648),e=+e,isNaN(e)&&(e=o?0:t.length-1),e<0&&(e=t.length+e),e>=t.length){if(o)return-1;e=t.length-1}else if(e<0){if(!o)return-1;e=0}if("string"==typeof r&&(r=ge.from(r,n)),we(r))return 0===r.length?-1:je(t,r,e,n,o);if("number"==typeof r)return r&=255,ge.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,r,e):Uint8Array.prototype.lastIndexOf.call(t,r,e):je(t,[r],e,n,o);throw new TypeError("val must be string, number or Buffer")}function je(t,r,e,n,o){var i,u=1,a=t.length,f=r.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||r.length<2)return-1;u=2,a/=2,f/=2,e/=2}function s(t,r){return 1===u?t[r]:t.readUInt16BE(r*u)}if(o){var c=-1;for(i=e;ia&&(e=a-f),i=e;i>=0;i--){for(var h=!0,p=0;po&&(n=o):n=o;var i=r.length;if(i%2!=0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var u=0;u>8,o=e%256,i.push(o),i.push(n);return i}(r,t.length-e),t,e,n)}function Be(t,r,e){return 0===r&&e===t.length?ae(t):ae(t.slice(r,e))}function Ne(t,r,e){e=Math.min(t.length,e);for(var n=[],o=r;o239?4:s>223?3:s>191?2:1;if(o+h<=e)switch(h){case 1:s<128&&(c=s);break;case 2:128==(192&(i=t[o+1]))&&(f=(31&s)<<6|63&i)>127&&(c=f);break;case 3:i=t[o+1],u=t[o+2],128==(192&i)&&128==(192&u)&&(f=(15&s)<<12|(63&i)<<6|63&u)>2047&&(f<55296||f>57343)&&(c=f);break;case 4:i=t[o+1],u=t[o+2],a=t[o+3],128==(192&i)&&128==(192&u)&&128==(192&a)&&(f=(15&s)<<18|(63&i)<<12|(63&u)<<6|63&a)>65535&&f<1114112&&(c=f)}null===c?(c=65533,h=1):c>65535&&(c-=65536,n.push(c>>>10&1023|55296),c=56320|1023&c),n.push(c),o+=h}return function(t){var r=t.length;if(r<=4096)return String.fromCharCode.apply(String,t);var e="",n=0;for(;n0&&(t=this.toString("hex",0,50).match(/.{2}/g).join(" "),this.length>50&&(t+=" ... ")),""},ge.prototype.compare=function(t,r,e,n,o){if(!we(t))throw new TypeError("Argument must be a Buffer");if(void 0===r&&(r=0),void 0===e&&(e=t?t.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),r<0||e>t.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&r>=e)return 0;if(n>=o)return-1;if(r>=e)return 1;if(this===t)return 0;for(var i=(o>>>=0)-(n>>>=0),u=(e>>>=0)-(r>>>=0),a=Math.min(i,u),f=this.slice(n,o),s=t.slice(r,e),c=0;co)&&(e=o),t.length>0&&(e<0||r<0)||r>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return Pe(this,t,r,e);case"utf8":case"utf-8":return Re(this,t,r,e);case"ascii":return Oe(this,t,r,e);case"latin1":case"binary":return Te(this,t,r,e);case"base64":return Se(this,t,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Ue(this,t,r,e);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},ge.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Ie(t,r,e){var n="";e=Math.min(t.length,e);for(var o=r;on)&&(e=n);for(var o="",i=r;ie)throw new RangeError("Trying to access beyond buffer length")}function De(t,r,e,n,o,i){if(!we(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(r>o||rt.length)throw new RangeError("Index out of range")}function Le(t,r,e,n){r<0&&(r=65535+r+1);for(var o=0,i=Math.min(t.length-e,2);o>>8*(n?o:1-o)}function ze(t,r,e,n){r<0&&(r=4294967295+r+1);for(var o=0,i=Math.min(t.length-e,4);o>>8*(n?o:3-o)&255}function Fe(t,r,e,n,o,i){if(e+n>t.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function qe(t,r,e,n,o){return o||Fe(t,0,e,4),se(t,r,e,n,23,4),e+4}function Je(t,r,e,n,o){return o||Fe(t,0,e,8),se(t,r,e,n,52,8),e+8}ge.prototype.slice=function(t,r){var e,n=this.length;if((t=~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),(r=void 0===r?n:~~r)<0?(r+=n)<0&&(r=0):r>n&&(r=n),r0&&(o*=256);)n+=this[t+--r]*o;return n},ge.prototype.readUInt8=function(t,r){return r||ke(t,1,this.length),this[t]},ge.prototype.readUInt16LE=function(t,r){return r||ke(t,2,this.length),this[t]|this[t+1]<<8},ge.prototype.readUInt16BE=function(t,r){return r||ke(t,2,this.length),this[t]<<8|this[t+1]},ge.prototype.readUInt32LE=function(t,r){return r||ke(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},ge.prototype.readUInt32BE=function(t,r){return r||ke(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},ge.prototype.readIntLE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=this[t],o=1,i=0;++i=(o*=128)&&(n-=Math.pow(2,8*r)),n},ge.prototype.readIntBE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=r,o=1,i=this[t+--n];n>0&&(o*=256);)i+=this[t+--n]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*r)),i},ge.prototype.readInt8=function(t,r){return r||ke(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},ge.prototype.readInt16LE=function(t,r){r||ke(t,2,this.length);var e=this[t]|this[t+1]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt16BE=function(t,r){r||ke(t,2,this.length);var e=this[t+1]|this[t]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt32LE=function(t,r){return r||ke(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},ge.prototype.readInt32BE=function(t,r){return r||ke(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},ge.prototype.readFloatLE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!0,23,4)},ge.prototype.readFloatBE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!1,23,4)},ge.prototype.readDoubleLE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!0,52,8)},ge.prototype.readDoubleBE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!1,52,8)},ge.prototype.writeUIntLE=function(t,r,e,n){(t=+t,r|=0,e|=0,n)||De(this,t,r,e,Math.pow(2,8*e)-1,0);var o=1,i=0;for(this[r]=255&t;++i=0&&(i*=256);)this[r+o]=t/i&255;return r+e},ge.prototype.writeUInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,255,0),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[r]=255&t,r+1},ge.prototype.writeUInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeUInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeUInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r+3]=t>>>24,this[r+2]=t>>>16,this[r+1]=t>>>8,this[r]=255&t):ze(this,t,r,!0),r+4},ge.prototype.writeUInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeIntLE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=0,u=1,a=0;for(this[r]=255&t;++i>0)-a&255;return r+e},ge.prototype.writeIntBE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=e-1,u=1,a=0;for(this[r+i]=255&t;--i>=0&&(u*=256);)t<0&&0===a&&0!==this[r+i+1]&&(a=1),this[r+i]=(t/u>>0)-a&255;return r+e},ge.prototype.writeInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,127,-128),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[r]=255&t,r+1},ge.prototype.writeInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8,this[r+2]=t>>>16,this[r+3]=t>>>24):ze(this,t,r,!0),r+4},ge.prototype.writeInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeFloatLE=function(t,r,e){return qe(this,t,r,!0,e)},ge.prototype.writeFloatBE=function(t,r,e){return qe(this,t,r,!1,e)},ge.prototype.writeDoubleLE=function(t,r,e){return Je(this,t,r,!0,e)},ge.prototype.writeDoubleBE=function(t,r,e){return Je(this,t,r,!1,e)},ge.prototype.copy=function(t,r,e,n){if(e||(e=0),n||0===n||(n=this.length),r>=t.length&&(r=t.length),r||(r=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-r=0;--o)t[o+r]=this[o+e];else if(i<1e3||!ge.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,e=void 0===e?this.length:e>>>0,t||(t=0),"number"==typeof t)for(i=r;i55295&&e<57344){if(!o){if(e>56319){(r-=3)>-1&&i.push(239,191,189);continue}if(u+1===n){(r-=3)>-1&&i.push(239,191,189);continue}o=e;continue}if(e<56320){(r-=3)>-1&&i.push(239,191,189),o=e;continue}e=65536+(o-55296<<10|e-56320)}else o&&(r-=3)>-1&&i.push(239,191,189);if(o=null,e<128){if((r-=1)<0)break;i.push(e)}else if(e<2048){if((r-=2)<0)break;i.push(e>>6|192,63&e|128)}else if(e<65536){if((r-=3)<0)break;i.push(e>>12|224,e>>6&63|128,63&e|128)}else{if(!(e<1114112))throw new Error("Invalid code point");if((r-=4)<0)break;i.push(e>>18|240,e>>12&63|128,e>>6&63|128,63&e|128)}}return i}function Ve(t){return function(t){var r,e,n,o,i,u;oe||ie();var a=t.length;if(a%4>0)throw new Error("Invalid string. Length must be a multiple of 4");i="="===t[a-2]?2:"="===t[a-1]?1:0,u=new ne(3*a/4-i),n=i>0?a-4:a;var f=0;for(r=0,e=0;r>16&255,u[f++]=o>>8&255,u[f++]=255&o;return 2===i?(o=ee[t.charCodeAt(r)]<<2|ee[t.charCodeAt(r+1)]>>4,u[f++]=255&o):1===i&&(o=ee[t.charCodeAt(r)]<<10|ee[t.charCodeAt(r+1)]<<4|ee[t.charCodeAt(r+2)]>>2,u[f++]=o>>8&255,u[f++]=255&o),u}(function(t){if((t=function(t){if(t.trim)return t.trim();return t.replace(/^\s+|\s+$/g,"")}(t).replace($e,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function He(t,r,e,n){for(var o=0;o=r.length||o>=t.length);++o)r[o+e]=t[o];return o}function We(t){return null!=t&&(!!t._isBuffer||Ze(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&Ze(t.slice(0,0))}(t))}function Ze(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}var Ke=function(t,r){if(r instanceof Error){var e={};return Object.getOwnPropertyNames(r).forEach((function(t){e[t]=r[t]})),e}return r};var Xe=function(t,r){try{var e=t.headers.accept.split(",");return r?e.filter((function(t){return t===r})):e}catch(t){return[]}},tn=function(t,r){return!!Xe(t,r).length},rn=function(t,r){return t.path===r.jsonqlPath};exports.VERSION="1.2.2",exports.buff=function(t,r){return void 0===r&&(r="base64"),We(t)?t:new ge.from(t,r)},exports.cacheBurst=Yr,exports.cacheBurstUrl=function(t){return Cr(t,Yr())},exports.chainFns=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},exports.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):xr(t,e)}))}))}),Promise.resolve(!1===r?[]:j(r)?r:{}))},exports.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("acknowledge_reply",t,r,e)},exports.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},exports.createMutation=Jr,exports.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Jr(t,r,e,n))},exports.createQuery=qr,exports.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},exports.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("emit_reply",t,r,e)},exports.createWsReply=Xr,exports.dasherize=Ir,exports.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ur("Unknown "+r+" to extract argument from!")}},exports.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Tr(e,r);return n}catch(t){throw new Tr(e,t)}},exports.extractSocketPart=Br,exports.extractWsPayload=function(t,r){void 0===r&&(r=Z);try{var e,n=W(t);if(!1!==(e=te(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ur("payload can not decoded",t)}catch(t){return r("error",t)}},exports.findFromContract=function(t,e,n){return!!(n[t]&&n[t][e]&&n[t][e].file&&r.existsSync(n[t][e].file))&&n[t][e].file},exports.formatPayload=Lr,exports.getCallMethod=function(t){switch(!0){case t===Rr[0]:return"query";case t===Rr[1]:return"mutation";default:return!1}},exports.getConfigValue=function(t,r){return r&&j(r)&&t in r?r[t]:void 0},exports.getDocLen=function(t){return ge.byteLength(t,"utf8")},exports.getMutationFromArgs=Qr,exports.getMutationFromPayload=function(t){var r=Gr(t,Qr);if(!1!==r)return r;throw new Sr("[getMutationArgs] Payload is malformed!",t)},exports.getNamespace=Wr,exports.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},exports.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Wr(t),o=e?Hr(r):function(t,r){var e,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},exports.getPathToFn=function(t,n,o){var i=o.resolverDir,u=Ir(t),a=[];o.contract&&o.contract[n]&&o.contract[n].path&&a.push(o.contract[n].path),a.push(e.join(i,n,u,[Or,Pr].join("."))),a.push(e.join(i,n,[u,Pr].join(".")));for(var f=a.length,s=0;s Date: Tue, 17 Mar 2020 14:50:20 +0800 Subject: [PATCH 24/66] making some major changes in the internal --- packages/ws-client-core/package.json | 2 +- packages/ws-client-core/src/api.js | 43 +++--- .../src/listener/client-event-listerner.js | 127 +++++++----------- .../src/listener/event-listerners.js | 109 ++++++++++----- 4 files changed, 151 insertions(+), 130 deletions(-) diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json index 2d4aff61..834a5111 100644 --- a/packages/ws-client-core/package.json +++ b/packages/ws-client-core/package.json @@ -58,7 +58,7 @@ "jsonql-constants": "^2.0.4", "jsonql-errors": "^1.2.1", "jsonql-params-validator": "^1.6.1", - "jsonql-utils": "^1.2.1" + "jsonql-utils": "^1.2.2" }, "devDependencies": { "ava": "^3.5.0", diff --git a/packages/ws-client-core/src/api.js b/packages/ws-client-core/src/api.js index 7848973b..ef5d2cd8 100644 --- a/packages/ws-client-core/src/api.js +++ b/packages/ws-client-core/src/api.js @@ -9,36 +9,43 @@ import { createRequiredParams } from './options' - /** * 0.5.0 we break up the wsClientCore in two parts one without the config check * @param {function} socketClientListerner - * @param {object} config the already checked config + * @return {function} to actually generate the client */ -export function wsClientCoreAction(socketClientListerner, config) { - return postCheckInjectOpts(config) - // the following two moved to wsPostConfig - .then(createRequiredParams) - .then( - ({opts, nspMap, ee}) => callersGenerator(opts, nspMap, ee) - ) - .then( - ({opts, nspMap, ee}) => socketClientListerner(opts, nspMap, ee) - ) - .catch(err => { - console.error(`jsonql-ws-core-client init error`, err) - }) +export function wsClientCoreAction(socketClientListerner) { + /** + * This is a breaking change, to continue the onion skin design + * @param {object} config the already checked config + * @return {promise} resolve the client + */ + return (config = {}) => { + + return postCheckInjectOpts(config) + // the following two moved to wsPostConfig + .then(createRequiredParams) + .then( + ({opts, nspMap, ee}) => callersGenerator(opts, nspMap, ee) + ) + .then( + ({opts, nspMap, ee}) => socketClientListerner(opts, nspMap, ee) + ) + .catch(err => { + console.error(`jsonql-ws-core-client init error`, err) + }) + } } /** * The main interface which will generate the socket clients and map all events - * @param {object} frameworkSocketEngine this is the one method export by various clients + * @param {object} socketClientListerner this is the one method export by various clients * @param {object} [configCheckMap={}] we should do all the checking in the core instead of the client * @param {object} [constProps={}] add this to supply the constProps from the downstream client * @return {function} accept a config then return the wsClient instance with all the available API */ -export function wsClientCore(frameworkSocketEngine, configCheckMap = {}, constProps = {}) { +export function wsClientCore(socketClientListerner, configCheckMap = {}, constProps = {}) { // we need to inject property to this client later return (config = {}) => checkConfiguration(config, configCheckMap, constProps) - .then(opts => wsClientCoreAction(frameworkSocketEngine, opts)) + .then(wsClientCoreAction(socketClientListerner)) } diff --git a/packages/ws-client-core/src/listener/client-event-listerner.js b/packages/ws-client-core/src/listener/client-event-listerner.js index d89a666a..e6632162 100644 --- a/packages/ws-client-core/src/listener/client-event-listerner.js +++ b/packages/ws-client-core/src/listener/client-event-listerner.js @@ -2,93 +2,66 @@ // @TODO port what is in the ws-main-handler // because all the client side call are via the ee // and that makes it re-usable between different client setup -import { - LOGOUT_EVENT_NAME, - NOT_LOGIN_ERR_MSG, - ON_ERROR_FN_NAME, - ON_RESULT_FN_NAME, - DISCONNECT_EVENT_NAME -} from 'jsonql-constants' -import { EMIT_EVT, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants' -import { createEvt, clearMainEmitEvt } from '../utils' -import { triggerNamespacesOnError } from './trigger-namespaces-on-error' - -/** - * A Event handler placeholder when it's not connect to the private nsp - * @param {string} namespace nsp - * @param {object} ee EventEmitter - * @param {object} opts configuration - * @return {void} - */ -const notLoginWsHandler = (namespace, ee, opts) => { - const { log } = opts - ee.$only( - createEvt(namespace, EMIT_EVT), - function notLoginHandlerCallback(resolverName, args) { - log('[notLoginHandler] hijack the ws call', namespace, resolverName, args) - const 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 handler, but wrap inside the error key - ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }]) - } - ) -} +/* +Inside the map call but we take it out for now and until the WebSocket version is fully working +import { SOCKET_IO } from '../options/constants' + // @TODO need to double check this + if (opts.serverType === SOCKET_IO) { + let { nspGroup } = nspMap + args.push(nspGroup[namespace]) + } +*/ +import { getPrivateNamespace } from 'jsonql-utils/src/namespace' +import { logoutEvtListerner, notLoginListerner } from './event-listerners' /** * centralize all the comm in one place - * @param {object} opts configuration - * @param {object} nspMap this is not in the opts - * @param {object} ee Event Emitter instance * @param {function} bindSocketEventHandler binding the ee to ws --> this is the core bit * @param {object} nsps namespaced nsp * @return {void} nothing */ -export function clientEventListerner(opts, nspMap, ee, bindSocketEventHandler, nsps) { - // since all these params already in the opts - const { log } = opts - const { namespaces } = nspMap - // @1.1.3 add isPrivate prop to id which namespace is the private nsp - // then we can use this prop to determine if we need to fire the ON_LOGIN_PROP_NAME event - const privateNamespace = getPrivateNamespace(namespaces) - let isPrivate = false - let hasPrivate = false - // loop - // @BUG for io this has to be in order the one with auth need to get call first - // The order of login is very import we need to run in order here to make sure - // one is execute then the other - namespaces.forEach(namespace => { - isPrivate = privateNamespace === namespace - if (!hasPrivate) { - hasPrivate = isPrivate - } - // log(namespace, ' --> nsps --> ', nsps[namespace]) - if (nsps[namespace]) { +export function clientEventListerner(bindSocketEventHandler, nsps) { + /** + * BREAKING CHANGE instead of one flat structure + * we return a function to accept the two + * @param {object} opts configuration + * @param {object} nspMap this is not in the opts + * @param {object} ee Event Emitter instance + * @return {array} although we return something but this is the last step and nothing to do further + */ + return (opts, nspMap, ee) => { + // since all these params already in the opts + const { log } = opts + const { namespaces } = nspMap + // @1.1.3 add isPrivate prop to id which namespace is the private nsp + // then we can use this prop to determine if we need to fire the ON_LOGIN_PROP_NAME event + const privateNamespace = getPrivateNamespace(namespaces) + + return namespaces.map(namespace => { + let isPrivate = privateNamespace === namespace + log(namespace, ` --> ${isPrivate ? 'private': 'public'} nsp --> `, nsps[namespace] !== false) + if (nsps[namespace]) { + log('[call bindWsHandler]', isPrivate, namespace) - log('[call bindWsHandler]', isPrivate, namespace) - let args = [namespace, nsps[namespace], ee, isPrivate, opts] - // @TODO need to double check this - if (opts.serverType === SOCKET_IO) { - let { nspGroup } = nspMap - args.push(nspGroup[namespace]) + let args = [namespace, nsps[namespace], ee, isPrivate, opts] + // Finally we binding everything together + Reflect.apply(bindSocketEventHandler, null, args) + + } else { + log(`binding notLoginWsHandler to ${namespace}`) + // a dummy placeholder + // @TODO but it should be a not connect handler + // when it's not login (or fail) this should be handle differently + notLoginListerner(namespace, ee, opts) + } + if (isPrivate) { + log(`Has private and add logoutEvtHandler`) + logoutEvtListerner(nsps, namespaces, ee, opts) } - Reflect.apply(bindSocketEventHandler, null, args) - } else { - log(`binding notLoginWsHandler to ${namespace}`) - // a dummy placeholder - // @TODO but it should be a not connect handler - // when it's not login (or fail) this should be handle differently - notLoginWsHandler(namespace, ee, opts) - } - }) - // logout event handler - if (hasPrivate) { - log(`Has private and add logoutEvtHandler`) - // logoutEvtHandler(nsps, namespaces, ee, opts) + // just return something its not going to get use anywhere + return isPrivate + }) } - // finally the disconnect event handlers - // disconnectHandler(nsps, namespaces, ee, opts) } diff --git a/packages/ws-client-core/src/listener/event-listerners.js b/packages/ws-client-core/src/listener/event-listerners.js index 4dc867d1..2e519cf8 100644 --- a/packages/ws-client-core/src/listener/event-listerners.js +++ b/packages/ws-client-core/src/listener/event-listerners.js @@ -1,4 +1,14 @@ // NOT IN USE AT THE MOMENT JUST KEEP IT HERE FOR THE TIME BEING +import { + LOGOUT_EVENT_NAME, + NOT_LOGIN_ERR_MSG, + ON_ERROR_FN_NAME, + ON_RESULT_FN_NAME, + DISCONNECT_EVENT_NAME +} from 'jsonql-constants' +import { EMIT_EVT, DISCONNECTED_ERROR_MSG } from '../options/constants' +import { createEvt, clearMainEmitEvt } from '../utils' +import { triggerNamespacesOnError } from './trigger-namespaces-on-error' /** * Only when there is a private namespace then we bind to this event @@ -8,48 +18,52 @@ * @param {object} opts configuration * @return {void} */ -const logoutEvtHandler = (nsps, namespaces, ee, opts) => { +export const logoutEvtListerner = (nsps, namespaces, ee, opts) => { const { log } = opts // this will be available regardless enableAuth // because the server can log the client out - ee.$on(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() { - const privateNamespace = getPrivateNamespace(namespaces) - log(`${LOGOUT_EVENT_NAME} event triggered`) - // disconnect(nsps, opts.serverType) - // we need to issue error to all the namespace onError handler - triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME) - // rebind all of the handler to the fake one - log(`logout from ${privateNamespace}`) + ee.$on( + LOGOUT_EVENT_NAME, + function logoutEvtCallback() { + const privateNamespace = getPrivateNamespace(namespaces) + log(`${LOGOUT_EVENT_NAME} event triggered`) + // disconnect(nsps, opts.serverType) + // we need to issue error to all the namespace onError Listerner + triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME) + // rebind all of the Listerner to the fake one + log(`logout from ${privateNamespace}`) - clearMainEmitEvt(ee, privateNamespace) - // we need to issue one more call to the server before we disconnect - // now this is a catch 22, here we are not suppose to do anything platform specific - // so that should fire before trigger this event - // clear out the nsp - nsps[privateNamespace] = null - // add a NOT LOGIN error if call - notLoginWsHandler(privateNamespace, ee, opts) - }) + clearMainEmitEvt(ee, privateNamespace) + // we need to issue one more call to the server before we disconnect + // now this is a catch 22, here we are not suppose to do anything platform specific + // so that should fire before trigger this event + // clear out the nsp + nsps[privateNamespace] = null + // add a NOT LOGIN error if call + notLoginWsListerner(privateNamespace, ee, opts) + } + ) } /** - * A Event handler placeholder when it's not connect to any nsp + * A Event Listerner placeholder when it's not connect to any nsp * @param {string} namespace nsp * @param {object} ee EventEmitter * @param {object} opts configuration * @return {void} */ -const disconnectedHandler = (namespace, ee, opts) => { +export const notConnectedListerner = (namespace, ee, opts) => { const { log } = opts + ee.$only( createEvt(namespace, EMIT_EVT), - function disconnectedHandlerCallback(resolverName, args) { - log(`[disconnectedHandler] hijack the ws call`, namespace, resolverName, args) + function disconnectedEvtCallback(resolverName, args) { + log(`[disconnectedListerner] hijack the ws call`, namespace, resolverName, args) const error = { message: DISCONNECTED_ERROR_MSG } ee.$call(createEvt(namespace, resolverName, ON_ERROR_FN_NAME), [ error ]) - // also trigger the result handler, but wrap inside the error key + // also trigger the result Listerner, but wrap inside the error key ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }]) } ) @@ -57,7 +71,7 @@ const disconnectedHandler = (namespace, ee, opts) => { /** - * The disconnect event handler, now we log the client out from everything + * The disconnect event Listerner, now we log the client out from everything * @TODO now we are another problem they disconnect, how to reconnect * @param {object} nsps the available nsp(s) * @param {array} namespaces available namespace @@ -65,16 +79,43 @@ const disconnectedHandler = (namespace, ee, opts) => { * @param {object} opts configuration * @return {void} */ -const disconnectHandler = (nsps, namespaces, ee, opts) => { +export const disconnectListerner = (nsps, namespaces, ee, opts) => { const { log } = opts - ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() { - triggerNamespacesOnError(ee, namespaces, DISCONNECT_EVENT_NAME) - namespaces.forEach( namespace => { - log(`disconnect from ${namespace}`) + ee.$on( + DISCONNECT_EVENT_NAME, + function disconnectEvtCallback() { + triggerNamespacesOnError(ee, namespaces, DISCONNECT_EVENT_NAME) + namespaces.forEach( namespace => { + log(`disconnect from ${namespace}`) - clearMainEmitEvt(ee, namespace) - nsps[namespace] = null - disconnectedHandler(namespace, ee, opts) - }) - }) + clearMainEmitEvt(ee, namespace) + nsps[namespace] = null + disconnectedListerner(namespace, 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} + */ +export const notLoginListerner = (namespace, ee, opts) => { + const { log } = opts + + ee.$only( + createEvt(namespace, EMIT_EVT), + function notLoginListernerCallback(resolverName, args) { + log('[notLoginListerner] hijack the ws call', namespace, resolverName, args) + const 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 }]) + } + ) } \ No newline at end of file -- Gitee From 12c2564bb927e192ad802e750534c5c47a37840d Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 14:54:18 +0800 Subject: [PATCH 25/66] Fix typo in the naming --- packages/ws-client-core/index.js | 2 +- ...ent-event-listerner.js => client-event-listener.js} | 10 +++++----- .../{event-listerners.js => event-listeners.js} | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) rename packages/ws-client-core/src/listener/{client-event-listerner.js => client-event-listener.js} (88%) rename packages/ws-client-core/src/listener/{event-listerners.js => event-listeners.js} (94%) diff --git a/packages/ws-client-core/index.js b/packages/ws-client-core/index.js index 37c2526e..dcbda33e 100644 --- a/packages/ws-client-core/index.js +++ b/packages/ws-client-core/index.js @@ -19,7 +19,7 @@ import { import { triggerNamespacesOnError, handleNamespaceOnError -} from './src/share/trigger-namespaces-on-error' +} from './src/listener/trigger-namespaces-on-error' import { getEventEmitter, EventEmitterClass diff --git a/packages/ws-client-core/src/listener/client-event-listerner.js b/packages/ws-client-core/src/listener/client-event-listener.js similarity index 88% rename from packages/ws-client-core/src/listener/client-event-listerner.js rename to packages/ws-client-core/src/listener/client-event-listener.js index e6632162..7aa76708 100644 --- a/packages/ws-client-core/src/listener/client-event-listerner.js +++ b/packages/ws-client-core/src/listener/client-event-listener.js @@ -13,7 +13,7 @@ import { SOCKET_IO } from '../options/constants' } */ import { getPrivateNamespace } from 'jsonql-utils/src/namespace' -import { logoutEvtListerner, notLoginListerner } from './event-listerners' +import { logoutEvtListener, notLoginListener } from './event-listeners' /** @@ -22,7 +22,7 @@ import { logoutEvtListerner, notLoginListerner } from './event-listerners' * @param {object} nsps namespaced nsp * @return {void} nothing */ -export function clientEventListerner(bindSocketEventHandler, nsps) { +export function clientEventListener(bindSocketEventListener, nsps) { /** * BREAKING CHANGE instead of one flat structure * we return a function to accept the two @@ -47,18 +47,18 @@ export function clientEventListerner(bindSocketEventHandler, nsps) { let args = [namespace, nsps[namespace], ee, isPrivate, opts] // Finally we binding everything together - Reflect.apply(bindSocketEventHandler, null, args) + Reflect.apply(bindSocketEventListener, null, args) } else { log(`binding notLoginWsHandler to ${namespace}`) // a dummy placeholder // @TODO but it should be a not connect handler // when it's not login (or fail) this should be handle differently - notLoginListerner(namespace, ee, opts) + notLoginListener(namespace, ee, opts) } if (isPrivate) { log(`Has private and add logoutEvtHandler`) - logoutEvtListerner(nsps, namespaces, ee, opts) + logoutEvtListener(nsps, namespaces, ee, opts) } // just return something its not going to get use anywhere return isPrivate diff --git a/packages/ws-client-core/src/listener/event-listerners.js b/packages/ws-client-core/src/listener/event-listeners.js similarity index 94% rename from packages/ws-client-core/src/listener/event-listerners.js rename to packages/ws-client-core/src/listener/event-listeners.js index 2e519cf8..e297c250 100644 --- a/packages/ws-client-core/src/listener/event-listerners.js +++ b/packages/ws-client-core/src/listener/event-listeners.js @@ -18,7 +18,7 @@ import { triggerNamespacesOnError } from './trigger-namespaces-on-error' * @param {object} opts configuration * @return {void} */ -export const logoutEvtListerner = (nsps, namespaces, ee, opts) => { +export const logoutEvtListener = (nsps, namespaces, ee, opts) => { const { log } = opts // this will be available regardless enableAuth // because the server can log the client out @@ -52,7 +52,7 @@ export const logoutEvtListerner = (nsps, namespaces, ee, opts) => { * @param {object} opts configuration * @return {void} */ -export const notConnectedListerner = (namespace, ee, opts) => { +export const notConnectedListener = (namespace, ee, opts) => { const { log } = opts ee.$only( @@ -79,7 +79,7 @@ export const notConnectedListerner = (namespace, ee, opts) => { * @param {object} opts configuration * @return {void} */ -export const disconnectListerner = (nsps, namespaces, ee, opts) => { +export const disconnectListener = (nsps, namespaces, ee, opts) => { const { log } = opts ee.$on( DISCONNECT_EVENT_NAME, @@ -103,7 +103,7 @@ export const disconnectListerner = (nsps, namespaces, ee, opts) => { * @param {object} opts configuration * @return {void} */ -export const notLoginListerner = (namespace, ee, opts) => { +export const notLoginListener = (namespace, ee, opts) => { const { log } = opts ee.$only( -- Gitee From 2a1d8fbb3ede0831ecd0870bbef50aee2d71caa1 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 15:27:20 +0800 Subject: [PATCH 26/66] rename from resolver-methods to generator-methods to make more sense --- packages/ws-client-core/index.js | 10 ++-- packages/ws-client-core/src/api.js | 6 +-- .../src/callers/callers-generator.js | 21 ++++----- ...solver-methods.js => generator-methods.js} | 47 +++++++++++-------- 4 files changed, 46 insertions(+), 38 deletions(-) rename packages/ws-client-core/src/callers/{resolver-methods.js => generator-methods.js} (73%) diff --git a/packages/ws-client-core/index.js b/packages/ws-client-core/index.js index dcbda33e..c43ffd49 100644 --- a/packages/ws-client-core/index.js +++ b/packages/ws-client-core/index.js @@ -14,7 +14,7 @@ import * as jsonqlWsConstants from './src/options/constants' import { createNspClient, createNspAuthClient -} from './src/share/create-nsp-clients' +} from './src/listener/create-nsp-clients' // error handler import { triggerNamespacesOnError, @@ -31,8 +31,8 @@ import { } from './src/utils/helpers' // this one bind the framework engine and our event engine together import { - clientEventHandler -} from './src/share/client-event-handler' + clientEventListener +} from './src/listener/client-event-listener' // The onion skin cooker import { createCombineClient @@ -42,7 +42,7 @@ import { createInitPing, extractPingResult, createIntercomPayload -} from './src/share/intercom-methods' +} from './src/listener/intercom-methods' // export export { @@ -68,7 +68,7 @@ export { getEventEmitter, EventEmitterClass, - clientEventHandler, + clientEventListener, createCombineClient, createInitPing, diff --git a/packages/ws-client-core/src/api.js b/packages/ws-client-core/src/api.js index ef5d2cd8..04106bc2 100644 --- a/packages/ws-client-core/src/api.js +++ b/packages/ws-client-core/src/api.js @@ -25,12 +25,12 @@ export function wsClientCoreAction(socketClientListerner) { return postCheckInjectOpts(config) // the following two moved to wsPostConfig .then(createRequiredParams) - .then( - ({opts, nspMap, ee}) => callersGenerator(opts, nspMap, ee) - ) .then( ({opts, nspMap, ee}) => socketClientListerner(opts, nspMap, ee) ) + .then( // there is problem here, we wrap up the operation inside + ({opts, nspMap, ee}) => callersGenerator(opts, nspMap, ee) + ) .catch(err => { console.error(`jsonql-ws-core-client init error`, err) }) diff --git a/packages/ws-client-core/src/callers/callers-generator.js b/packages/ws-client-core/src/callers/callers-generator.js index 7884676b..e580bf0f 100644 --- a/packages/ws-client-core/src/callers/callers-generator.js +++ b/packages/ws-client-core/src/callers/callers-generator.js @@ -5,9 +5,9 @@ import { chainFns } from '../utils' import { createAuthMethods } from './setup-auth-methods' import { generateResolvers, - createNamespaceErrorHandler, - createOnReadyHandler -} from './resolver-methods' + createOnReadyListener, + createNamespaceErrorListener +} from './generator-methods' import { setupFinalStep } from './setup-final-step' @@ -23,22 +23,21 @@ import { * @public */ export function callersGenerator(opts, nspMap, ee) { - - let args = [ + let fns = [ generateResolvers, - createNamespaceErrorHandler, - createOnReadyHandler + createOnReadyListener, + createNamespaceErrorListener ] if (opts.enableAuth) { - args.push( + fns.push( createAuthMethods ) } // we will always get back the [ obj, opts, ee ] // then we only return the obj (wsClient) - args.push(setupFinalStep) + fns.push(setupFinalStep) // run it - const fn = Reflect.apply(chainFns, null, args) + const generator = Reflect.apply(chainFns, null, fns) - return fn(opts, ee, nspMap[NSP_GROUP]) + return generator(opts, ee, nspMap[NSP_GROUP]) } diff --git a/packages/ws-client-core/src/callers/resolver-methods.js b/packages/ws-client-core/src/callers/generator-methods.js similarity index 73% rename from packages/ws-client-core/src/callers/resolver-methods.js rename to packages/ws-client-core/src/callers/generator-methods.js index 347f1e29..acb302ed 100644 --- a/packages/ws-client-core/src/callers/resolver-methods.js +++ b/packages/ws-client-core/src/callers/generator-methods.js @@ -59,7 +59,11 @@ export function generateResolvers(opts, ee, nspGroup) { let fn = createResolver(ee, namespace, resolverName, params, log) // this should set as a getter therefore can not be overwrite by accident // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee) - client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log)) + client = injectToFn( + client, + resolverName, + setupResolver(namespace, resolverName, params, fn, ee, log) + ) } } // resolve the clientto start the chain @@ -76,21 +80,22 @@ export function generateResolvers(opts, ee, nspGroup) { * @param {object} nspGroup namespace keys * @return {array} [obj, opts, ee] */ -export function createNamespaceErrorHandler(client, opts, ee, nspGroup) { +export function createNamespaceErrorListener(client, opts, ee, nspGroup) { return [ - // using the onError as name - // @TODO we should follow the convention earlier - // make this a setter for the clientitself - objDefineProps(client, ON_ERROR_FN_NAME, function namespaceErrorCallbackHandler(namespaceErrorHandler) { - if (isFunc(namespaceErrorHandler)) { - // please note ON_ERROR_FN_NAME can add multiple listners - for (let namespace in nspGroup) { - // this one is very tricky, we need to make sure the trigger is calling - // with the namespace as well as the error - ee.$on(createEvt(namespace, ON_ERROR_FN_NAME), namespaceErrorHandler) + objDefineProps( + client, + ON_ERROR_FN_NAME, + function namespaceErrorCallbackHandler(namespaceErrorHandler) { + if (isFunc(namespaceErrorHandler)) { + // please note ON_ERROR_FN_NAME can add multiple listners + for (let namespace in nspGroup) { + // this one is very tricky, we need to make sure the trigger is calling + // with the namespace as well as the error + ee.$on(createEvt(namespace, ON_ERROR_FN_NAME), namespaceErrorHandler) + } } } - }), + ), opts, ee ] @@ -103,14 +108,18 @@ export function createNamespaceErrorHandler(client, opts, ee, nspGroup) { * @param {object} ee Event Emitter * @return {array} [ obj, opts, ee ] */ -export function createOnReadyHandler(client, opts, ee) { +export function createOnReadyListener(client, opts, ee) { return [ - objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) { - if (isFunc(onReadyCallback)) { - // reduce it down to just one flat level - ee.$on(ON_READY_FN_NAME, onReadyCallback) + objDefineProps( + client, + ON_READY_FN_NAME, + function onReadyCallbackHandler(onReadyCallback) { + if (isFunc(onReadyCallback)) { + // reduce it down to just one flat level + ee.$on(ON_READY_FN_NAME, onReadyCallback) + } } - }), + ), opts, ee ] -- Gitee From b49de20c7f80c66b984455eab658fb6da7ade63f Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 15:32:14 +0800 Subject: [PATCH 27/66] Finish the rewrite now run the test to see where is broken --- .../ws-client-core/src/callers/callers-generator.js | 5 ++--- packages/ws-client-core/src/create-combine-client.js | 2 +- .../ws-client-core/tests/fixtures/lib/mock-client.js | 12 +++--------- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/packages/ws-client-core/src/callers/callers-generator.js b/packages/ws-client-core/src/callers/callers-generator.js index e580bf0f..7dec6b11 100644 --- a/packages/ws-client-core/src/callers/callers-generator.js +++ b/packages/ws-client-core/src/callers/callers-generator.js @@ -14,6 +14,7 @@ import { import { NSP_GROUP } from 'jsonql-constants' + /** * prepare the methods * @param {object} opts configuration @@ -29,9 +30,7 @@ export function callersGenerator(opts, nspMap, ee) { createNamespaceErrorListener ] if (opts.enableAuth) { - fns.push( - createAuthMethods - ) + fns.push(createAuthMethods) } // we will always get back the [ obj, opts, ee ] // then we only return the obj (wsClient) diff --git a/packages/ws-client-core/src/create-combine-client.js b/packages/ws-client-core/src/create-combine-client.js index 676abf8a..b3f03b70 100644 --- a/packages/ws-client-core/src/create-combine-client.js +++ b/packages/ws-client-core/src/create-combine-client.js @@ -30,7 +30,7 @@ function createCombineClient(httpClientConstructor, wsClientEngine, configCheckM return httpClientConstructor(opts) }) .then(httpClient => { - const socketClient = wsClientCoreAction(wsClientEngine, opts) + const socketClient = wsClientCoreAction(wsClientEngine)(opts) httpClient[SOCKET_NAME] = socketClient return httpClient }) diff --git a/packages/ws-client-core/tests/fixtures/lib/mock-client.js b/packages/ws-client-core/tests/fixtures/lib/mock-client.js index 5568318c..0d3f497e 100644 --- a/packages/ws-client-core/tests/fixtures/lib/mock-client.js +++ b/packages/ws-client-core/tests/fixtures/lib/mock-client.js @@ -1,11 +1,5 @@ -import { - // wsCoreDefaultOptions, - // wsCoreConstProps, - // postWsOptions, - // wsClientCore, - wsClientCoreAction, - // checkSocketClientType -} from '../../../index' +// create a headless mock client +import { wsClientCoreAction } from '../../../index' import { join } from 'path' import { fakeWsClient, log } from './fake-ws-client' import { checkConfiguration } from '../../../src/options/index' @@ -31,7 +25,7 @@ function mockClient(enableAuth = false) { log(`mockClient opts after checkConfiguration`, config) return config }) - .then(config => wsClientCoreAction(fakeWsClient, config)) + .then(wsClientCoreAction(fakeWsClient)) } export { mockClient, log } -- Gitee From 54e2bd2228b4dc43d61cefa0ad76e2d33d966b00 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 15:37:00 +0800 Subject: [PATCH 28/66] Something everything is working again ... WTF --- packages/ws-client-core/src/listener/intercom-methods.js | 2 +- packages/ws-client-core/tests/init.test.js | 8 ++++---- packages/ws-client-core/tests/options.test.js | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/ws-client-core/src/listener/intercom-methods.js b/packages/ws-client-core/src/listener/intercom-methods.js index 6ea85d49..58258430 100644 --- a/packages/ws-client-core/src/listener/intercom-methods.js +++ b/packages/ws-client-core/src/listener/intercom-methods.js @@ -19,7 +19,7 @@ import { } from 'jsonql-utils/module' import { JsonqlError -} from '../callers/node_modules/jsonql-errors' +} from 'jsonql-errors' const CSRF_HEADER_NOT_EXIST_ERR = 'CSRF header is not in the received payload' /** diff --git a/packages/ws-client-core/tests/init.test.js b/packages/ws-client-core/tests/init.test.js index b3117235..6de14504 100644 --- a/packages/ws-client-core/tests/init.test.js +++ b/packages/ws-client-core/tests/init.test.js @@ -1,6 +1,6 @@ // testing the init connection const test = require('ava') -const wsNodeClient = require('jsonql-ws-server/client') +const { basicClient } = require('jsonql-ws-server/client') const wsServer = require('./fixtures/server-setup') const { JSONQL_PATH @@ -8,7 +8,7 @@ const { const debug = require('debug')('jsonql-ws-server:test:ws') const port = 8899 -const { createInitPing, extractPingResult } = require('../src/share/intercom-methods') +const { createInitPing, extractPingResult } = require('../src/listener/intercom-methods') test.before(async t => { const { app } = await wsServer() @@ -16,7 +16,7 @@ test.before(async t => { t.context.server = app t.context.server.listen(port) - t.context.client = wsNodeClient(`ws://localhost:${port}/${JSONQL_PATH}`) + t.context.client = basicClient(`ws://localhost:${port}/${JSONQL_PATH}`) }) test.after(t => { @@ -47,7 +47,7 @@ test.cb(`Testing the init ping call`, t => { debug('header', header) // t.end() // reinit the client with an options - const newClient = wsNodeClient(`ws://localhost:${port}/${JSONQL_PATH}`, false, header) + const newClient = basicClient(`ws://localhost:${port}/${JSONQL_PATH}`, false, header) newClient.on('open', () => { t.end() diff --git a/packages/ws-client-core/tests/options.test.js b/packages/ws-client-core/tests/options.test.js index d7bfc79e..69a9802d 100644 --- a/packages/ws-client-core/tests/options.test.js +++ b/packages/ws-client-core/tests/options.test.js @@ -3,7 +3,7 @@ const test = require('ava') const debug = require('debug')('jsonql-ws-client:test:options') const { injectToFn, chainFns } = require('jsonql-utils') const constants = require('../src/options/constants') -const { triggerNamespacesOnError } = require('../src/share/trigger-namespaces-on-error') +const { triggerNamespacesOnError } = require('../src/listener/trigger-namespaces-on-error') const { checkConfiguration } = require('../src/options') test(`Should have a debug logger pass from here`, async t => { -- Gitee From e6f7aca33342224e7dc06fca0b3b2938f83efefa Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 17:15:27 +0800 Subject: [PATCH 29/66] create a hello world method --- packages/ws-client-core/package.json | 4 +- packages/ws-client-core/tests/event.test.js | 2 +- packages/ws-client-core/tests/evt.test.js | 66 ++++++++++++++++++- .../src/handles/get-socket-handler.js | 5 +- .../src/handles/handle-hello.js | 10 +++ 5 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 packages/ws-server-core/src/handles/handle-hello.js diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json index 834a5111..6e168a3e 100644 --- a/packages/ws-client-core/package.json +++ b/packages/ws-client-core/package.json @@ -14,7 +14,8 @@ "prepare": "npm run test", "update:version": "node ./build.js", "test:tbd": "DEBUG=jsonql-ws* ava ./tests/tbd.test.js", - "test:evt": "ava ./tests/event.test.js", + "test:evt": "DEBUG=jsonql-ws* ava ./tests/evt.test.js", + "test:event": "DEBUG=jsonql-ws* ava ./tests/event.test.js", "test:init": "DEBUG=jsonql-ws* ava ./tests/init.test.js", "test:auth": "DEBUG=jsonql-ws* ava ./tests/auth.test.js", "test:node": "DEBUG=jsonql-ws-* ava ./tests/test-node.test.js", @@ -65,6 +66,7 @@ "esm": "^3.2.25", "fs-extra": "^8.1.0", "jsonql-contract": "^1.8.10", + "jsonql-jwt": "^1.3.10", "jsonql-ws-server": "^1.7.5", "kefir": "^3.8.6", "ws": "^7.2.3" diff --git a/packages/ws-client-core/tests/event.test.js b/packages/ws-client-core/tests/event.test.js index 4ee9b6fc..0e015cd6 100644 --- a/packages/ws-client-core/tests/event.test.js +++ b/packages/ws-client-core/tests/event.test.js @@ -1,6 +1,6 @@ // retest the nb-event-service here to try to figure out why some of the event not fired const test = require('ava') -const NbEventService = require('nb-event-service') +const NbEventService = require('@to1source/event') const debug = require('debug')('jsonql-ws-client:test:event') const { objDefineProps, injectToFn } = require('jsonql-utils') const { getEventEmitter } = require('../src/utils/get-event-emitter') diff --git a/packages/ws-client-core/tests/evt.test.js b/packages/ws-client-core/tests/evt.test.js index 18c58d84..eca31cde 100644 --- a/packages/ws-client-core/tests/evt.test.js +++ b/packages/ws-client-core/tests/evt.test.js @@ -1,14 +1,76 @@ // testing the event, especially the switching to stimulate // the pre-login / post-login situation const test = require('ava') +const { join } = require('path') +const { JSONQL_PATH } = require('jsonql-constants') const Event = require('@to1source/event') + const debug = require('debug') const logger = debug('jsonql-ws-client:test:evt:logger') -const db = debug('jsonql-ws-client:test:evt') +const localDebug = debug('jsonql-ws-client:test:evt') + +const { chainPromises } = require('jsonql-utils') +const { basicClient } = require('jsonql-ws-server/client') + +const wsServer = require('./fixtures/server-setup') +const createToken = require('./fixtures/token') + +const port = 9001 +const baseUrl = `ws://localhost:${port}/${JSONQL_PATH}` +const userdata = {name: 'Joel', id: 1} + +const asyncClient = (url, token) => { + return Promise.resolve(basicClient(url, token)) +} +const namespaces = ['public', 'private'] + -test.before(t => { +test.before(async t => { t.context.evt = new Event({ logger }) + + const { app } = await wsServer({ + enableAuth: true, + keysDir: join(__dirname, 'fixtures', 'keys') + }) + + t.context.server = app + t.context.server.listen(port) + + t.context.token = createToken(userdata) + + t.context.clients = await chainPromises([ + asyncClient([baseUrl, namespaces[0]].join('/')), + asyncClient([baseUrl, namespaces[1]].join('/'), t.context.token) + ]) + .map((client, i) => { + return {[namespaces[i]]: client} + }) + .reduce((a, b) => Object.assign(a, b), {}) + }) +test.after(t => { + t.context.server.close() +}) + +test.cb(`Test the chainPromises to create client`, t => { + + t.plan(2) + + const c1 = t.context.clients.public + const c2 = t.context.clients.private + + c1.onopen = function() { + t.pass() + } + + c2.onopen = function() { + t.pass() + t.end() + } + +}) + + test.todo(`Testing the switch over callback binding`) diff --git a/packages/ws-server-core/src/handles/get-socket-handler.js b/packages/ws-server-core/src/handles/get-socket-handler.js index 3c10df54..04aa1667 100644 --- a/packages/ws-server-core/src/handles/get-socket-handler.js +++ b/packages/ws-server-core/src/handles/get-socket-handler.js @@ -1,3 +1,4 @@ +// The top level socket handler and redistribute task const { INTERCOM_RESOLVER_NAME, NSP_GROUP @@ -5,6 +6,7 @@ const { const { getResolverFromPayload } = require('jsonql-utils') const { handleInterCom } = require('./handle-intercom') const { handleNspResolvers } = require('./handle-nsp-resolvers') +const { handleHello } = require('./handle-hello') const { getRainbowDebug } = require('../share/helpers') @@ -50,7 +52,8 @@ function getSocketHandler(config, ws, deliverFn, req, connectedNamespace, payloa debug('getSocketHandler:intercom') // We don't need to send anything back // @TBC do we need the config return handleInterCom(config, ws, deliverFn, req, connectedNamespace, args, userdata) - + case resolverName === HELLO_FN: + return handleHello(deliverFn) default: const contractParam = matchResolverByNamespace(resolverName, connectedNamespace, nspGroup) if (contractParam === false) { diff --git a/packages/ws-server-core/src/handles/handle-hello.js b/packages/ws-server-core/src/handles/handle-hello.js new file mode 100644 index 00000000..8e905ed1 --- /dev/null +++ b/packages/ws-server-core/src/handles/handle-hello.js @@ -0,0 +1,10 @@ +// create a hello world method to test the installation +const { deliverMsg } = require('../share/resolver-methods') +const { HELLO_FN, HELLO } = require('jsonql-constants') + +function handleHello(deliverFn) { + + deliverMsg(deliverFn, HELLO_FN, HELLO) +} + +module.exports = { handleHello } \ No newline at end of file -- Gitee From 24fb0ed2393d48d937dd3bfd070c743aaef5d65e Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 17:24:45 +0800 Subject: [PATCH 30/66] implement the handleUnknownPayload --- packages/constants/socket.js | 1 - .../ws-server-core/src/handles/get-socket-handler.js | 7 +++++-- .../src/handles/handle-unknown-payload.js | 8 ++++++-- packages/ws-server/src/modules.js | 5 ++--- packages/ws-server/tests/send.test.js | 11 ++++++++--- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/packages/constants/socket.js b/packages/constants/socket.js index b346ef53..58d306d1 100644 --- a/packages/constants/socket.js +++ b/packages/constants/socket.js @@ -61,7 +61,6 @@ export const USERDATA_PROP_NAME = 'userdata' export const EMIT_REPLY_TYPE = 'emit_reply' export const ACKNOWLEDGE_REPLY_TYPE = 'acknowledge_reply' - export const NSP_GROUP = 'nspGroup' export const PUBLIC_NAMESPACE = 'publicNamespace' diff --git a/packages/ws-server-core/src/handles/get-socket-handler.js b/packages/ws-server-core/src/handles/get-socket-handler.js index 04aa1667..4691a70a 100644 --- a/packages/ws-server-core/src/handles/get-socket-handler.js +++ b/packages/ws-server-core/src/handles/get-socket-handler.js @@ -1,12 +1,14 @@ // The top level socket handler and redistribute task const { INTERCOM_RESOLVER_NAME, - NSP_GROUP + NSP_GROUP, + HELLO_FN } = require('jsonql-constants') const { getResolverFromPayload } = require('jsonql-utils') const { handleInterCom } = require('./handle-intercom') const { handleNspResolvers } = require('./handle-nsp-resolvers') const { handleHello } = require('./handle-hello') +const { handleUnknownPayload } = require('./handle-unknown-payload') const { getRainbowDebug } = require('../share/helpers') @@ -57,7 +59,8 @@ function getSocketHandler(config, ws, deliverFn, req, connectedNamespace, payloa default: const contractParam = matchResolverByNamespace(resolverName, connectedNamespace, nspGroup) if (contractParam === false) { - return // exit + // just return an error + return handleUnknownPayload(deliverFn, resolverName, args) } debug('getSocketHandler:default', contractParam) handleNspResolvers(deliverFn, ws, resolverName, args, contractParam.params, config, userdata) diff --git a/packages/ws-server-core/src/handles/handle-unknown-payload.js b/packages/ws-server-core/src/handles/handle-unknown-payload.js index 7c8b974b..3ce250b5 100644 --- a/packages/ws-server-core/src/handles/handle-unknown-payload.js +++ b/packages/ws-server-core/src/handles/handle-unknown-payload.js @@ -1,5 +1,7 @@ const { getDebug } = require('../share/helpers') const debug = getDebug('handle-intercome') +const { deliverMsg } = require('../share/resolver-methods') +const { ERROR_KEY } = require('jsonql-constants') /** * @TODO not sure what to do with this one, perhaps just log it @@ -12,9 +14,11 @@ const debug = getDebug('handle-intercome') * @param {*} userdata it could be empty most of the time * @return {void} nothing return just send back a reply */ -function handleUnknownPayload(config, ws, deliverFn, req, connectedNamespace, args, userdata) { +function handleUnknownPayload(deliverFn, resolverName, args) { debug(`Handle unknown payload called with argument`, args) - Reflect.apply(deliverFn, null, args) + // Reflect.apply(deliverFn, null, args) + + deliverMsg(deliverFn, resolverName, {[ERROR_KEY]: 'UNKNOWN'}) } module.exports = { handleUnknownPayload } diff --git a/packages/ws-server/src/modules.js b/packages/ws-server/src/modules.js index 3370f107..34ea89ac 100644 --- a/packages/ws-server/src/modules.js +++ b/packages/ws-server/src/modules.js @@ -19,10 +19,9 @@ const { SOCKET_STATE_KEY, getSocketHandler -} = require('jsonql-ws-server-core') -// require('../../ws-server-core') +} = require('../../ws-server-core') +// require('jsonql-ws-server-core') - module.exports = { WebSocket, // ours diff --git a/packages/ws-server/tests/send.test.js b/packages/ws-server/tests/send.test.js index 09237870..d5c8b744 100644 --- a/packages/ws-server/tests/send.test.js +++ b/packages/ws-server/tests/send.test.js @@ -4,7 +4,7 @@ const { join } = require('path') const fsx = require('fs-extra') const { basicClient } = require('../client') const wsServer = require('./fixtures/server') -const { JSONQL_PATH } = require('jsonql-constants') +const { JSONQL_PATH, HELLO_FN } = require('jsonql-constants') const { extractWsPayload } = require('jsonql-ws-server-core') const createPayload = require('./fixtures/create-payload') const contractDir = join(__dirname, 'fixtures', 'contract', 'send') @@ -47,10 +47,15 @@ test.cb(`Testing the send method from within the resolver`, t => { } }) - client.on('open', () => { ts = Date.now() - client.send( createPayload('testSend', 'Knock knock', ts)) + + client.send( createPayload(HELLO_FN, 'Just say hi')) + + // client.send( createPayload('testSend', 'Knock knock', ts)) + + + }) }) \ No newline at end of file -- Gitee From 15b05945c16789bb229a87e6aaa63c82a3112c90 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 17:32:57 +0800 Subject: [PATCH 31/66] jsonql-ws-core 0.7.8 --- packages/ws-server-core/package.json | 4 ++-- .../src/handles/handle-unknown-payload.js | 5 ++--- packages/ws-server/tests/send.test.js | 14 +++++++------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/ws-server-core/package.json b/packages/ws-server-core/package.json index 5377eb35..749308e9 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.7.7", + "version": "0.7.8", "description": "This is the core module that drive the Jsonql WS Socket server, not for direct use.", "main": "index.js", "files": [ @@ -36,7 +36,7 @@ "jsonql-jwt": "^1.3.10", "jsonql-params-validator": "^1.6.1", "jsonql-resolver": "^1.1.3", - "jsonql-utils": "^1.2.1", + "jsonql-utils": "^1.2.2", "lodash": "^4.17.15", "nanoid": "^2.1.11", "node-cache": "^5.1.0" diff --git a/packages/ws-server-core/src/handles/handle-unknown-payload.js b/packages/ws-server-core/src/handles/handle-unknown-payload.js index 3ce250b5..5d065699 100644 --- a/packages/ws-server-core/src/handles/handle-unknown-payload.js +++ b/packages/ws-server-core/src/handles/handle-unknown-payload.js @@ -1,6 +1,6 @@ const { getDebug } = require('../share/helpers') const debug = getDebug('handle-intercome') -const { deliverMsg } = require('../share/resolver-methods') +const { handleError } = require('../share/resolver-methods') const { ERROR_KEY } = require('jsonql-constants') /** @@ -16,9 +16,8 @@ const { ERROR_KEY } = require('jsonql-constants') */ function handleUnknownPayload(deliverFn, resolverName, args) { debug(`Handle unknown payload called with argument`, args) - // Reflect.apply(deliverFn, null, args) - deliverMsg(deliverFn, resolverName, {[ERROR_KEY]: 'UNKNOWN'}) + handleError(deliverFn, resolverName, 'UNKNOWN') } module.exports = { handleUnknownPayload } diff --git a/packages/ws-server/tests/send.test.js b/packages/ws-server/tests/send.test.js index d5c8b744..39a82b96 100644 --- a/packages/ws-server/tests/send.test.js +++ b/packages/ws-server/tests/send.test.js @@ -32,7 +32,7 @@ test.after(t => { test.cb(`Testing the send method from within the resolver`, t => { - t.plan(2) + t.plan(3) let ts let tested = 0 let client = t.context.client @@ -42,19 +42,19 @@ test.cb(`Testing the send method from within the resolver`, t => { let json = extractWsPayload(data) debug(tested+'', json) t.pass() - if (tested>1) { + if (tested>2) { t.end() } }) client.on('open', () => { ts = Date.now() - + // test with real resolver + client.send( createPayload('testSend', 'Knock knock', ts)) + // test hello world method client.send( createPayload(HELLO_FN, 'Just say hi')) - - // client.send( createPayload('testSend', 'Knock knock', ts)) - - + // test the unknown handler + client.send( createPayload('whatever', 'na na na') ) }) -- Gitee From 1909e289215f3f9aa0a314fea69812d0995602ea Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 19:01:19 +0800 Subject: [PATCH 32/66] update modules test passed --- packages/ws-server/package.json | 6 +++--- packages/ws-server/src/modules.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json index a0e3399c..9a472324 100755 --- a/packages/ws-server/package.json +++ b/packages/ws-server/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-ws-server", - "version": "1.7.5", + "version": "1.7.6", "description": "Setup WebSocket server for the jsonql to run on the same host, automatic generate public / private channel using contract", "main": "index.js", "files": [ @@ -34,8 +34,8 @@ "colors": "^1.4.0", "debug": "^4.1.1", "jsonql-constants": "^2.0.4", - "jsonql-utils": "^1.2.1", - "jsonql-ws-server-core": "^0.7.7", + "jsonql-utils": "^1.2.2", + "jsonql-ws-server-core": "^0.7.8", "ws": "^7.2.3" }, "devDependencies": { diff --git a/packages/ws-server/src/modules.js b/packages/ws-server/src/modules.js index 34ea89ac..efd17d82 100644 --- a/packages/ws-server/src/modules.js +++ b/packages/ws-server/src/modules.js @@ -19,8 +19,8 @@ const { SOCKET_STATE_KEY, getSocketHandler -} = require('../../ws-server-core') -// require('jsonql-ws-server-core') +} = require('jsonql-ws-server-core') +// require('../../ws-server-core') module.exports = { WebSocket, -- Gitee From cf165ad326c991be074c8d97fd723a0371f540eb Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 20:41:44 +0800 Subject: [PATCH 33/66] found the problem why the nspInfo was screw, it was because the contract was wrong so add a check and if that happen it throw error and stop the init --- packages/ws-client-core/package.json | 2 +- packages/ws-client-core/tests/evt.test.js | 17 ++++++++--------- .../tests/fixtures/server-setup.js | 10 +++++++--- packages/ws-server-core/package.json | 2 +- .../src/handles/handle-disconnet.js | 2 +- packages/ws-server-core/src/options/index.js | 12 ++++++++++-- packages/ws-server/src/core/create-ws-server.js | 2 +- .../src/core/security/create-verify-client.js | 13 ++++++++++--- packages/ws-server/src/modules.js | 5 +++-- 9 files changed, 42 insertions(+), 23 deletions(-) diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json index 6e168a3e..7fd9ad0f 100644 --- a/packages/ws-client-core/package.json +++ b/packages/ws-client-core/package.json @@ -67,7 +67,7 @@ "fs-extra": "^8.1.0", "jsonql-contract": "^1.8.10", "jsonql-jwt": "^1.3.10", - "jsonql-ws-server": "^1.7.5", + "jsonql-ws-server": "^1.7.6", "kefir": "^3.8.6", "ws": "^7.2.3" }, diff --git a/packages/ws-client-core/tests/evt.test.js b/packages/ws-client-core/tests/evt.test.js index eca31cde..ef5c632a 100644 --- a/packages/ws-client-core/tests/evt.test.js +++ b/packages/ws-client-core/tests/evt.test.js @@ -24,7 +24,6 @@ const asyncClient = (url, token) => { } const namespaces = ['public', 'private'] - test.before(async t => { t.context.evt = new Event({ logger }) @@ -39,14 +38,14 @@ test.before(async t => { t.context.token = createToken(userdata) t.context.clients = await chainPromises([ - asyncClient([baseUrl, namespaces[0]].join('/')), - asyncClient([baseUrl, namespaces[1]].join('/'), t.context.token) - ]) - .map((client, i) => { - return {[namespaces[i]]: client} - }) - .reduce((a, b) => Object.assign(a, b), {}) - + asyncClient([baseUrl, namespaces[1]].join('/'), t.context.token), + asyncClient([baseUrl, namespaces[0]].join('/')) + ]).then(clients => clients + .map((client, i) => { + return {[namespaces[i]]: client} + }) + .reduce((a, b) => Object.assign(a, b), {}) + ) }) test.after(t => { diff --git a/packages/ws-client-core/tests/fixtures/server-setup.js b/packages/ws-client-core/tests/fixtures/server-setup.js index 92dc86d7..ef2cf2c3 100644 --- a/packages/ws-client-core/tests/fixtures/server-setup.js +++ b/packages/ws-client-core/tests/fixtures/server-setup.js @@ -5,9 +5,9 @@ const { join } = require('path') // const { JSONQL_PATH } = require('jsonql-constants') const resolverDir = join(__dirname, 'resolvers') -const contractDir = join(__dirname, 'contract') -// require('../../../ws-server') -const { jsonqlWsServer } = require('jsonql-ws-server') + + +const { jsonqlWsServer } = require('../../../ws-server') //require('jsonql-ws-server') // start const server = http.createServer(function(req, res) { @@ -17,6 +17,10 @@ const server = http.createServer(function(req, res) { }) module.exports = function(extra = {}) { + + const contractDir = extra.enableAuth ? join(__dirname, 'contract', 'auth') + : join(__dirname, 'contract') + // extra.contract = extra.contract || contract; return new Promise(resolver => { jsonqlWsServer( diff --git a/packages/ws-server-core/package.json b/packages/ws-server-core/package.json index 749308e9..282a1877 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.7.8", + "version": "0.7.9", "description": "This is the core module that drive the Jsonql WS Socket server, not for direct use.", "main": "index.js", "files": [ diff --git a/packages/ws-server-core/src/handles/handle-disconnet.js b/packages/ws-server-core/src/handles/handle-disconnet.js index 4fe89450..06156483 100644 --- a/packages/ws-server-core/src/handles/handle-disconnet.js +++ b/packages/ws-server-core/src/handles/handle-disconnet.js @@ -14,7 +14,7 @@ * @return {void} nothing return just send back a reply */ function handleDisconnect(config, ws, deliverFn, req, connectedNamespace, args, userdata) { - + // @TODO } module.exports = { handleDisconnect } \ No newline at end of file diff --git a/packages/ws-server-core/src/options/index.js b/packages/ws-server-core/src/options/index.js index 2385a0f0..320f3056 100644 --- a/packages/ws-server-core/src/options/index.js +++ b/packages/ws-server-core/src/options/index.js @@ -23,6 +23,8 @@ const { socketAppProps } = require('./props') +const debug = require('debug')('jsonql-ws-server-core:options') + /** * We need this to find the socket server type @@ -54,8 +56,14 @@ function initWsServerOption(config) { .then(getContract) // processing the key .then(opts => { + const nspInfo = getNspInfoByConfig(opts) + 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) + } // @0.7.0 add a new property to the config object - opts.nspInfo = getNspInfoByConfig(opts) + opts.nspInfo = nspInfo // next the auth server options if (opts.enableAuth === true) { // @TODO should get rip of this useJwt as string and @@ -63,7 +71,7 @@ function initWsServerOption(config) { opts.publicKey = fsx.readFileSync(join(opts.keysDir, [PUBLIC_KEY_NAME, PEM_EXT].join('.'))) opts.privateKey = fsx.readFileSync(join(opts.keysDir, [PRIVATE_KEY_NAME, PEM_EXT].join('.'))) } else { - throw new JsonqlValidationError(SECRET_MISSING_ERR) + throw new JsonqlValidationError(`initWsServerOption`, SECRET_MISSING_ERR) } } return opts diff --git a/packages/ws-server/src/core/create-ws-server.js b/packages/ws-server/src/core/create-ws-server.js index 78e9ce5e..674ad4ca 100644 --- a/packages/ws-server/src/core/create-ws-server.js +++ b/packages/ws-server/src/core/create-ws-server.js @@ -15,7 +15,7 @@ const generateNsp = config => { const { namespaces } = config.nspInfo //getNamespace(config) return namespaces .map(name => { - const verifyClient = createVerifyClient(name, config, config.publicKey) + const verifyClient = createVerifyClient(name, config) const opt = Object.assign({}, config.serverInitOption, { noServer: true, verifyClient }) // How do we pass more options here return { diff --git a/packages/ws-server/src/core/security/create-verify-client.js b/packages/ws-server/src/core/security/create-verify-client.js index 57b6d280..758b65d0 100644 --- a/packages/ws-server/src/core/security/create-verify-client.js +++ b/packages/ws-server/src/core/security/create-verify-client.js @@ -79,15 +79,15 @@ const localCb = msg => { * provide the necessary param to create the verifyClient function * @param {string} namespace the namespace to generate verifyClient for * @param {object} opts need to add this because from now on we will always verifyClient - * @param {string|buffer} publicKey for decoding * @param {object} [jwtOptions={}] optional pass to the jwtDecode * @param {function|boolean} [cb=false] if the token is invalid * @return {function} verifyClient method */ -function createVerifyClient(namespace, opts, publicKey, jwtOptions = {}, cb = localCb) { - const { enableAuth, nspInfo } = opts +function createVerifyClient(namespace, opts, jwtOptions = {}, cb = localCb) { + const { enableAuth, nspInfo, publicKey } = opts // This property now generate inside the ws-server-core const { publicNamespace } = nspInfo + /** * pass this as part of the option to the WebSocket at init time * @param {object} info we use the info.req.url to extract the token @@ -99,8 +99,15 @@ function createVerifyClient(namespace, opts, publicKey, jwtOptions = {}, cb = lo cb('Header check failed') return done(false) } + + debug('nspInfo', nspInfo) + + debug('what the fuck is happening here?', namespace, publicNamespace) + // also need to check if this is the private namespace as well! if (!enableAuth || namespace === publicNamespace) { + // cb(`public namespace no need to check`, namespace, publicNamespace) + return done(true) // job done here } // auth features diff --git a/packages/ws-server/src/modules.js b/packages/ws-server/src/modules.js index efd17d82..482e95a9 100644 --- a/packages/ws-server/src/modules.js +++ b/packages/ws-server/src/modules.js @@ -19,8 +19,9 @@ const { SOCKET_STATE_KEY, getSocketHandler -} = require('jsonql-ws-server-core') -// require('../../ws-server-core') +} = require('../../ws-server-core') +// require('jsonql-ws-server-core') + module.exports = { WebSocket, -- Gitee From 8cb3fb43de09151daf2643cf173323ec4e8d3a79 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 21:06:46 +0800 Subject: [PATCH 34/66] jsonql-utils 1.2.3 --- packages/utils/browser.js | 2 +- packages/utils/index.js | 2 ++ packages/utils/main.js | 2 +- packages/utils/module.js | 4 +++- packages/utils/package.json | 5 +++-- packages/utils/src/generic.js | 8 ++++++++ packages/utils/tests/construct.test.js | 22 +++++++++++++++++++++- 7 files changed, 39 insertions(+), 6 deletions(-) diff --git a/packages/utils/browser.js b/packages/utils/browser.js index fad23181..0448b2d8 100644 --- a/packages/utils/browser.js +++ b/packages/utils/browser.js @@ -1,2 +1,2 @@ -!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t=t||self).jsonqlUtils={})}(this,(function(t){"use strict";var r=Array.isArray,e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},n="object"==typeof e&&e&&e.Object===Object&&e,o="object"==typeof self&&self&&self.Object===Object&&self,u=n||o||Function("return this")(),i=u.Symbol,a=Object.prototype,c=a.hasOwnProperty,f=a.toString,s=i?i.toStringTag:void 0;var l=Object.prototype.toString;var p=i?i.toStringTag:void 0;function v(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":p&&p in Object(t)?function(t){var r=c.call(t,s),e=t[s];try{t[s]=void 0;var n=!0}catch(t){}var o=f.call(t);return n&&(r?t[s]=e:delete t[s]),o}(t):function(t){return l.call(t)}(t)}var d,y,h=(d=Object.getPrototypeOf,y=Object,function(t){return d(y(t))});function g(t){return null!=t&&"object"==typeof t}var _=Function.prototype,b=Object.prototype,j=_.toString,m=b.hasOwnProperty,w=j.call(Object);function O(t){if(!g(t)||"[object Object]"!=v(t))return!1;var r=h(t);if(null===r)return!0;var e=m.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&j.call(e)==w}var S=i?i.prototype:void 0,P=S?S.toString:void 0;function N(t){if("string"==typeof t)return t;if(r(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var u=Array(o);++n-1;);return e}(o,u),function(t,r){for(var e=t.length;e--&&E(r,t[e],0)>-1;);return e}(o,u)+1).join("")}var I=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return r(t)?t:[t]},L=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},V=function(t,r){try{var e=Object.keys(t);return I(e,r)}catch(t){return!1}},W=function(t){return L("string"==typeof t?t:JSON.stringify(t))},H=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function Z(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var X=Array.prototype.splice;function Y(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},Y.prototype.set=function(t,r){var e=this.__data__,n=Z(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function rt(t){if(!tt(t))return!1;var r=v(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var et,nt=u["__core-js_shared__"],ot=(et=/[^.]+$/.exec(nt&&nt.keys&&nt.keys.IE_PROTO||""))?"Symbol(src)_1."+et:"";var ut=Function.prototype.toString;var it=/^\[object .+?Constructor\]$/,at=Function.prototype,ct=Object.prototype,ft=at.toString,st=ct.hasOwnProperty,lt=RegExp("^"+ft.call(st).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pt(t){return!(!tt(t)||function(t){return!!ot&&ot in t}(t))&&(rt(t)?lt:it).test(function(t){if(null!=t){try{return ut.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function vt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pt(e)?e:void 0}var dt=vt(u,"Map"),yt=vt(Object,"create");var ht=Object.prototype.hasOwnProperty;var gt=Object.prototype.hasOwnProperty;function _t(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Gt(t.length)&&!rt(t)}var It="object"==typeof t&&t&&!t.nodeType&&t,Qt=It&&"object"==typeof module&&module&&!module.nodeType&&module,Lt=Qt&&Qt.exports===It?u.Buffer:void 0,Vt=(Lt?Lt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Ht="object"==typeof t&&t&&!t.nodeType&&t,Kt=Ht&&"object"==typeof module&&module&&!module.nodeType&&module,Zt=Kt&&Kt.exports===Ht&&n.process,Xt=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Zt&&Zt.binding&&Zt.binding("util")}catch(t){}}(),Yt=Xt&&Xt.isTypedArray,tr=Yt?function(t){return function(r){return t(r)}}(Yt):function(t){return g(t)&&Gt(t.length)&&!!Wt[v(t)]};function rr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var er=Object.prototype.hasOwnProperty;function nr(t,r,e){var n=t[r];er.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||Ot(t,r,e)}var or=/^(?:0|[1-9]\d*)$/;function ur(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&or.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(gr);function jr(t,r){return br(function(t,r,e){return r=hr(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,u=hr(n.length-r,0),i=Array(u);++o1?r[n-1]:void 0,u=n>2?r[2]:void 0;for(o=mr.length>3&&"function"==typeof o?(n--,o):void 0,u&&function(t,r,e){if(!tt(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ur(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],u)&&(o=n<3?void 0:o,n=1),t=Object(t);++e0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},t.chainProcessPromises=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return t.then((function(t){return r(t)}))}),Reflect.apply(t,null,e))}},t.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):wr(t,e)}))}))}),Promise.resolve(!1===r?[]:O(r)?r:{}))},t.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("acknowledge_reply",t,r,e)},t.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},t.createMutation=Ur,t.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Ur(t,r,e,n))},t.createQuery=qr,t.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},t.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("emit_reply",t,r,e)},t.createWsReply=Wr,t.dasherize=function(t){return $(t).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},t.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ar("Unknown "+r+" to extract argument from!")}},t.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Pr(e,r);return n}catch(t){throw new Pr(e,t)}},t.extractSocketPart=Tr,t.extractWsPayload=function(t,r){void 0===r&&(r=H);try{var e,n=W(t);if(!1!==(e=Hr(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ar("payload can not decoded",t)}catch(t){return r("error",t)}},t.formatPayload=Jr,t.getCallMethod=function(t){switch(!0){case t===Sr[0]:return"query";case t===Sr[1]:return"mutation";default:return!1}},t.getConfigValue=function(t,r){return r&&O(r)&&t in r?r[t]:void 0},t.getLogger=function(t){var r=[t];return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];try{window&&window.JSONQL_DEBUG&&Reflect.apply(console.info,console,r.concat(t))}catch(t){}}},t.getMutationFromArgs=Gr,t.getMutationFromPayload=function(t){var r=Dr(t,Gr);if(!1!==r)return r;throw new Nr("[getMutationArgs] Payload is malformed!",t)},t.getNamespace=Qr,t.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},t.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Qr(t),o=e?Ir(r):function(t,r){var e,n={};for(var o in t){var u=t[o];n[o]=u}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},t.getPrivateNamespace=function(t){return t.length>1&&t[0]},t.getQueryFromArgs=Br,t.getQueryFromPayload=function(t){var r=Dr(t,Br);if(!1!==r)return r;throw new Nr("[getQueryArgs] Payload is malformed!",t)},t.getRegex=function(t){switch(!0){case!0===Lr(t):return t;case!0===kr(t):return new RegExp(t);default:return!1}},t.getResolverFromPayload=Mr,t.groupByNamespace=Ir,t.inArray=I,t.injectToFn=function(t,r,e,n){void 0===n&&(n=!1);var o=Or(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t},t.isContract=function(t){return!!function(t){return O(t)&&(V(t,"query")||V(t,"mutation")||V(t,"socket"))}(t)&&t},t.isFunc=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},t.isJsonqlErrorObj=$r,t.isNotEmpty=function(t){return void 0!==t&&!1!==t&&null!==t&&""!==$(t)},t.isObjectHasKey=V,t.isRegExp=Lr,t.isWsReply=Hr,t.logger=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];try{window&&window.DEBUG&&Reflect.apply(console.log,console,t)}catch(t){}},t.nil=H,t.objDefineProps=function(t,r,e,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,r)&&Object.defineProperty(t,r,{set:e,get:null===n?function(){return null}:n}),t},t.objHasProp=Or,t.packError=function(t,r,e,n){var o;void 0===r&&(r="JsonqlError"),void 0===e&&(e=0),void 0===n&&(n="");var u={detail:t,className:r,statusCode:e,message:n};return JSON.stringify(((o={}).error=$r(t)||u,o.TS=[Er()],o))},t.packResult=function(t,e){void 0===e&&(e=!1);var n={};return n.data=t,e&&r(e)&&(e.push(Er()),n.TS=e),JSON.stringify(n)},t.parseJson=L,t.resultHandler=function(t){return V(t,"data")&&!V(t,"error")?t.data:t},t.timestamp=Er,t.toArray=Q,t.toJson=W,t.toPayload=Rr,t.urlParams=xr,Object.defineProperty(t,"__esModule",{value:!0})})); +!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t=t||self).jsonqlUtils={})}(this,(function(t){"use strict";var r=Array.isArray,e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},n="object"==typeof e&&e&&e.Object===Object&&e,o="object"==typeof self&&self&&self.Object===Object&&self,u=n||o||Function("return this")(),i=u.Symbol,a=Object.prototype,c=a.hasOwnProperty,f=a.toString,s=i?i.toStringTag:void 0;var l=Object.prototype.toString;var p=i?i.toStringTag:void 0;function v(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":p&&p in Object(t)?function(t){var r=c.call(t,s),e=t[s];try{t[s]=void 0;var n=!0}catch(t){}var o=f.call(t);return n&&(r?t[s]=e:delete t[s]),o}(t):function(t){return l.call(t)}(t)}var d,y,h=(d=Object.getPrototypeOf,y=Object,function(t){return d(y(t))});function g(t){return null!=t&&"object"==typeof t}var _=Function.prototype,b=Object.prototype,j=_.toString,m=b.hasOwnProperty,O=j.call(Object);function w(t){if(!g(t)||"[object Object]"!=v(t))return!1;var r=h(t);if(null===r)return!0;var e=m.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&j.call(e)==O}var S=i?i.prototype:void 0,P=S?S.toString:void 0;function N(t){if("string"==typeof t)return t;if(r(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var u=Array(o);++n-1;);return e}(o,u),function(t,r){for(var e=t.length;e--&&E(r,t[e],0)>-1;);return e}(o,u)+1).join("")}var I=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return r(t)?t:[t]},L=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},V=function(t,r){try{var e=Object.keys(t);return I(e,r)}catch(t){return!1}},W=function(t){return L("string"==typeof t?t:JSON.stringify(t))},H=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function Z(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var X=Array.prototype.splice;function Y(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},Y.prototype.set=function(t,r){var e=this.__data__,n=Z(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function rt(t){if(!tt(t))return!1;var r=v(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var et,nt=u["__core-js_shared__"],ot=(et=/[^.]+$/.exec(nt&&nt.keys&&nt.keys.IE_PROTO||""))?"Symbol(src)_1."+et:"";var ut=Function.prototype.toString;var it=/^\[object .+?Constructor\]$/,at=Function.prototype,ct=Object.prototype,ft=at.toString,st=ct.hasOwnProperty,lt=RegExp("^"+ft.call(st).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pt(t){return!(!tt(t)||function(t){return!!ot&&ot in t}(t))&&(rt(t)?lt:it).test(function(t){if(null!=t){try{return ut.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function vt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pt(e)?e:void 0}var dt=vt(u,"Map"),yt=vt(Object,"create");var ht=Object.prototype.hasOwnProperty;var gt=Object.prototype.hasOwnProperty;function _t(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Gt(t.length)&&!rt(t)}var It="object"==typeof t&&t&&!t.nodeType&&t,Qt=It&&"object"==typeof module&&module&&!module.nodeType&&module,Lt=Qt&&Qt.exports===It?u.Buffer:void 0,Vt=(Lt?Lt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Ht="object"==typeof t&&t&&!t.nodeType&&t,Kt=Ht&&"object"==typeof module&&module&&!module.nodeType&&module,Zt=Kt&&Kt.exports===Ht&&n.process,Xt=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Zt&&Zt.binding&&Zt.binding("util")}catch(t){}}(),Yt=Xt&&Xt.isTypedArray,tr=Yt?function(t){return function(r){return t(r)}}(Yt):function(t){return g(t)&&Gt(t.length)&&!!Wt[v(t)]};function rr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var er=Object.prototype.hasOwnProperty;function nr(t,r,e){var n=t[r];er.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||wt(t,r,e)}var or=/^(?:0|[1-9]\d*)$/;function ur(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&or.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(gr);function jr(t,r){return br(function(t,r,e){return r=hr(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,u=hr(n.length-r,0),i=Array(u);++o1?r[n-1]:void 0,u=n>2?r[2]:void 0;for(o=mr.length>3&&"function"==typeof o?(n--,o):void 0,u&&function(t,r,e){if(!tt(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ur(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],u)&&(o=n<3?void 0:o,n=1),t=Object(t);++e0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},t.chainProcessPromises=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return t.then((function(t){return r(t)}))}),Reflect.apply(t,null,e))}},t.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):Or(t,e)}))}))}),Promise.resolve(!1===r?[]:w(r)?r:{}))},t.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("acknowledge_reply",t,r,e)},t.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},t.createMutation=Ur,t.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Ur(t,r,e,n))},t.createQuery=qr,t.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},t.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("emit_reply",t,r,e)},t.createWsReply=Wr,t.dasherize=function(t){return $(t).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},t.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ar("Unknown "+r+" to extract argument from!")}},t.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Pr(e,r);return n}catch(t){throw new Pr(e,t)}},t.extractSocketPart=Tr,t.extractWsPayload=function(t,r){void 0===r&&(r=H);try{var e,n=W(t);if(!1!==(e=Hr(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ar("payload can not decoded",t)}catch(t){return r("error",t)}},t.formatPayload=Jr,t.getCallMethod=function(t){switch(!0){case t===Sr[0]:return"query";case t===Sr[1]:return"mutation";default:return!1}},t.getConfigValue=function(t,r){return r&&w(r)&&t in r?r[t]:void 0},t.getLogger=function(t){var r=[t];return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];try{window&&window.JSONQL_DEBUG&&Reflect.apply(console.info,console,r.concat(t))}catch(t){}}},t.getMutationFromArgs=Gr,t.getMutationFromPayload=function(t){var r=Dr(t,Gr);if(!1!==r)return r;throw new Nr("[getMutationArgs] Payload is malformed!",t)},t.getNamespace=Qr,t.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},t.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Qr(t),o=e?Ir(r):function(t,r){var e,n={};for(var o in t){var u=t[o];n[o]=u}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},t.getPrivateNamespace=function(t){return t.length>1&&t[0]},t.getQueryFromArgs=Br,t.getQueryFromPayload=function(t){var r=Dr(t,Br);if(!1!==r)return r;throw new Nr("[getQueryArgs] Payload is malformed!",t)},t.getRegex=function(t){switch(!0){case!0===Lr(t):return t;case!0===kr(t):return new RegExp(t);default:return!1}},t.getResolverFromPayload=Mr,t.groupByNamespace=Ir,t.inArray=I,t.injectToFn=function(t,r,e,n){void 0===n&&(n=!1);var o=wr(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t},t.isContract=function(t){return!!function(t){return w(t)&&(V(t,"query")||V(t,"mutation")||V(t,"socket"))}(t)&&t},t.isFunc=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},t.isJsonqlErrorObj=$r,t.isNotEmpty=function(t){return void 0!==t&&!1!==t&&null!==t&&""!==$(t)},t.isObjectHasKey=V,t.isRegExp=Lr,t.isWsReply=Hr,t.logger=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];try{window&&window.DEBUG&&Reflect.apply(console.log,console,t)}catch(t){}},t.nil=H,t.objDefineProps=function(t,r,e,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,r)&&Object.defineProperty(t,r,{set:e,get:null===n?function(){return null}:n}),t},t.objHasProp=wr,t.packError=function(t,r,e,n){var o;void 0===r&&(r="JsonqlError"),void 0===e&&(e=0),void 0===n&&(n="");var u={detail:t,className:r,statusCode:e,message:n};return JSON.stringify(((o={}).error=$r(t)||u,o.TS=[Er()],o))},t.packResult=function(t,e){void 0===e&&(e=!1);var n={};return n.data=t,e&&r(e)&&(e.push(Er()),n.TS=e),JSON.stringify(n)},t.parseJson=L,t.resultHandler=function(t){return V(t,"data")&&!V(t,"error")?t.data:t},t.timestamp=Er,t.toArray=Q,t.toJson=W,t.toPayload=Fr,t.urlParams=xr,Object.defineProperty(t,"__esModule",{value:!0})})); //# sourceMappingURL=browser.js.map diff --git a/packages/utils/index.js b/packages/utils/index.js index 26670cae..586d4b54 100644 --- a/packages/utils/index.js +++ b/packages/utils/index.js @@ -27,6 +27,7 @@ import { parseJson, isFunc, nil, + assign, // params-api toPayload, formatPayload, @@ -129,6 +130,7 @@ export { parseJson, isFunc, nil, + assign, // params-api toPayload, formatPayload, diff --git a/packages/utils/main.js b/packages/utils/main.js index 262c4d52..75d40904 100644 --- a/packages/utils/main.js +++ b/packages/utils/main.js @@ -1,2 +1,2 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t,r=(t=require("fs"))&&"object"==typeof t&&"default"in t?t.default:t,e=require("path"),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,u="object"==typeof self&&self&&self.Object===Object&&self,a=i||u||Function("return this")(),f=a.Symbol,s=Object.prototype,c=s.hasOwnProperty,h=s.toString,p=f?f.toStringTag:void 0;var l=Object.prototype.toString;var g=f?f.toStringTag:void 0;function y(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":g&&g in Object(t)?function(t){var r=c.call(t,p),e=t[p];try{t[p]=void 0;var n=!0}catch(t){}var o=h.call(t);return n&&(r?t[p]=e:delete t[p]),o}(t):function(t){return l.call(t)}(t)}var v,d,_=(v=Object.getPrototypeOf,d=Object,function(t){return v(d(t))});function b(t){return null!=t&&"object"==typeof t}var w=Function.prototype,m=Object.prototype,A=w.toString,E=m.hasOwnProperty,x=A.call(Object);function j(t){if(!b(t)||"[object Object]"!=y(t))return!1;var r=_(t);if(null===r)return!0;var e=E.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&A.call(e)==x}var P=f?f.prototype:void 0,R=P?P.toString:void 0;function O(t){if("string"==typeof t)return t;if(n(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var i=Array(o);++n-1;);return e}(o,i),function(t,r){for(var e=t.length;e--&&U(r,t[e],0)>-1;);return e}(o,i)+1).join("")}var G=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return n(t)?t:[t]},V=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},H=function(t,r){try{var e=Object.keys(t);return G(e,r)}catch(t){return!1}},W=function(t){return V("string"==typeof t?t:JSON.stringify(t))},Z=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function X(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var tt=Array.prototype.splice;function rt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},rt.prototype.set=function(t,r){var e=this.__data__,n=X(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function nt(t){if(!et(t))return!1;var r=y(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var ot,it=a["__core-js_shared__"],ut=(ot=/[^.]+$/.exec(it&&it.keys&&it.keys.IE_PROTO||""))?"Symbol(src)_1."+ot:"";var at=Function.prototype.toString;var ft=/^\[object .+?Constructor\]$/,st=Function.prototype,ct=Object.prototype,ht=st.toString,pt=ct.hasOwnProperty,lt=RegExp("^"+ht.call(pt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function gt(t){return!(!et(t)||function(t){return!!ut&&ut in t}(t))&&(nt(t)?lt:ft).test(function(t){if(null!=t){try{return at.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function yt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return gt(e)?e:void 0}var vt=yt(a,"Map"),dt=yt(Object,"create");var _t=Object.prototype.hasOwnProperty;var bt=Object.prototype.hasOwnProperty;function wt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Jt(t.length)&&!nt(t)}var Gt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Qt=Gt&&"object"==typeof module&&module&&!module.nodeType&&module,Vt=Qt&&Qt.exports===Gt?a.Buffer:void 0,Ht=(Vt?Vt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Zt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Kt=Zt&&"object"==typeof module&&module&&!module.nodeType&&module,Xt=Kt&&Kt.exports===Zt&&i.process,tr=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Xt&&Xt.binding&&Xt.binding("util")}catch(t){}}(),rr=tr&&tr.isTypedArray,er=rr?function(t){return function(r){return t(r)}}(rr):function(t){return b(t)&&Jt(t.length)&&!!Wt[y(t)]};function nr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var or=Object.prototype.hasOwnProperty;function ir(t,r,e){var n=t[r];or.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||jt(t,r,e)}var ur=/^(?:0|[1-9]\d*)$/;function ar(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&ur.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(br);function Ar(t,r){return mr(function(t,r,e){return r=_r(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,i=_r(n.length-r,0),u=Array(i);++o1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=Er.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!et(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ar(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e>18&63]+re[o>>12&63]+re[o>>6&63]+re[63&o]);return i.join("")}function ae(t){var r;oe||ie();for(var e=t.length,n=e%3,o="",i=[],u=0,a=e-n;ua?a:u+16383));return 1===n?(r=t[e-1],o+=re[r>>2],o+=re[r<<4&63],o+="=="):2===n&&(r=(t[e-2]<<8)+t[e-1],o+=re[r>>10],o+=re[r>>4&63],o+=re[r<<2&63],o+="="),i.push(o),i.join("")}function fe(t,r,e,n,o){var i,u,a=8*o-n-1,f=(1<>1,c=-7,h=e?o-1:0,p=e?-1:1,l=t[r+h];for(h+=p,i=l&(1<<-c)-1,l>>=-c,c+=a;c>0;i=256*i+t[r+h],h+=p,c-=8);for(u=i&(1<<-c)-1,i>>=-c,c+=n;c>0;u=256*u+t[r+h],h+=p,c-=8);if(0===i)i=1-s;else{if(i===f)return u?NaN:1/0*(l?-1:1);u+=Math.pow(2,n),i-=s}return(l?-1:1)*u*Math.pow(2,i-n)}function se(t,r,e,n,o,i){var u,a,f,s=8*i-o-1,c=(1<>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,l=n?0:i-1,g=n?1:-1,y=r<0||0===r&&1/r<0?1:0;for(r=Math.abs(r),isNaN(r)||r===1/0?(a=isNaN(r)?1:0,u=c):(u=Math.floor(Math.log(r)/Math.LN2),r*(f=Math.pow(2,-u))<1&&(u--,f*=2),(r+=u+h>=1?p/f:p*Math.pow(2,1-h))*f>=2&&(u++,f/=2),u+h>=c?(a=0,u=c):u+h>=1?(a=(r*f-1)*Math.pow(2,o),u+=h):(a=r*Math.pow(2,h-1)*Math.pow(2,o),u=0));o>=8;t[e+l]=255&a,l+=g,a/=256,o-=8);for(u=u<0;t[e+l]=255&u,l+=g,u/=256,s-=8);t[e+l-g]|=128*y}var ce={}.toString,he=Array.isArray||function(t){return"[object Array]"==ce.call(t)};function pe(){return ge.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function le(t,r){if(pe()=pe())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+pe().toString(16)+" bytes");return 0|t}function we(t){return!(null==t||!t._isBuffer)}function me(t,r){if(we(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var e=t.length;if(0===e)return 0;for(var n=!1;;)switch(r){case"ascii":case"latin1":case"binary":return e;case"utf8":case"utf-8":case void 0:return Qe(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*e;case"hex":return e>>>1;case"base64":return Ve(t).length;default:if(n)return Qe(t).length;r=(""+r).toLowerCase(),n=!0}}function Ae(t,r,e){var n=!1;if((void 0===r||r<0)&&(r=0),r>this.length)return"";if((void 0===e||e>this.length)&&(e=this.length),e<=0)return"";if((e>>>=0)<=(r>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return Ye(this,r,e);case"utf8":case"utf-8":return Ne(this,r,e);case"ascii":return Ie(this,r,e);case"latin1":case"binary":return Ce(this,r,e);case"base64":return Be(this,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Me(this,r,e);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function Ee(t,r,e){var n=t[r];t[r]=t[e],t[e]=n}function xe(t,r,e,n,o){if(0===t.length)return-1;if("string"==typeof e?(n=e,e=0):e>2147483647?e=2147483647:e<-2147483648&&(e=-2147483648),e=+e,isNaN(e)&&(e=o?0:t.length-1),e<0&&(e=t.length+e),e>=t.length){if(o)return-1;e=t.length-1}else if(e<0){if(!o)return-1;e=0}if("string"==typeof r&&(r=ge.from(r,n)),we(r))return 0===r.length?-1:je(t,r,e,n,o);if("number"==typeof r)return r&=255,ge.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,r,e):Uint8Array.prototype.lastIndexOf.call(t,r,e):je(t,[r],e,n,o);throw new TypeError("val must be string, number or Buffer")}function je(t,r,e,n,o){var i,u=1,a=t.length,f=r.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||r.length<2)return-1;u=2,a/=2,f/=2,e/=2}function s(t,r){return 1===u?t[r]:t.readUInt16BE(r*u)}if(o){var c=-1;for(i=e;ia&&(e=a-f),i=e;i>=0;i--){for(var h=!0,p=0;po&&(n=o):n=o;var i=r.length;if(i%2!=0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var u=0;u>8,o=e%256,i.push(o),i.push(n);return i}(r,t.length-e),t,e,n)}function Be(t,r,e){return 0===r&&e===t.length?ae(t):ae(t.slice(r,e))}function Ne(t,r,e){e=Math.min(t.length,e);for(var n=[],o=r;o239?4:s>223?3:s>191?2:1;if(o+h<=e)switch(h){case 1:s<128&&(c=s);break;case 2:128==(192&(i=t[o+1]))&&(f=(31&s)<<6|63&i)>127&&(c=f);break;case 3:i=t[o+1],u=t[o+2],128==(192&i)&&128==(192&u)&&(f=(15&s)<<12|(63&i)<<6|63&u)>2047&&(f<55296||f>57343)&&(c=f);break;case 4:i=t[o+1],u=t[o+2],a=t[o+3],128==(192&i)&&128==(192&u)&&128==(192&a)&&(f=(15&s)<<18|(63&i)<<12|(63&u)<<6|63&a)>65535&&f<1114112&&(c=f)}null===c?(c=65533,h=1):c>65535&&(c-=65536,n.push(c>>>10&1023|55296),c=56320|1023&c),n.push(c),o+=h}return function(t){var r=t.length;if(r<=4096)return String.fromCharCode.apply(String,t);var e="",n=0;for(;n0&&(t=this.toString("hex",0,50).match(/.{2}/g).join(" "),this.length>50&&(t+=" ... ")),""},ge.prototype.compare=function(t,r,e,n,o){if(!we(t))throw new TypeError("Argument must be a Buffer");if(void 0===r&&(r=0),void 0===e&&(e=t?t.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),r<0||e>t.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&r>=e)return 0;if(n>=o)return-1;if(r>=e)return 1;if(this===t)return 0;for(var i=(o>>>=0)-(n>>>=0),u=(e>>>=0)-(r>>>=0),a=Math.min(i,u),f=this.slice(n,o),s=t.slice(r,e),c=0;co)&&(e=o),t.length>0&&(e<0||r<0)||r>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return Pe(this,t,r,e);case"utf8":case"utf-8":return Re(this,t,r,e);case"ascii":return Oe(this,t,r,e);case"latin1":case"binary":return Te(this,t,r,e);case"base64":return Se(this,t,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Ue(this,t,r,e);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},ge.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Ie(t,r,e){var n="";e=Math.min(t.length,e);for(var o=r;on)&&(e=n);for(var o="",i=r;ie)throw new RangeError("Trying to access beyond buffer length")}function De(t,r,e,n,o,i){if(!we(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(r>o||rt.length)throw new RangeError("Index out of range")}function Le(t,r,e,n){r<0&&(r=65535+r+1);for(var o=0,i=Math.min(t.length-e,2);o>>8*(n?o:1-o)}function ze(t,r,e,n){r<0&&(r=4294967295+r+1);for(var o=0,i=Math.min(t.length-e,4);o>>8*(n?o:3-o)&255}function Fe(t,r,e,n,o,i){if(e+n>t.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function qe(t,r,e,n,o){return o||Fe(t,0,e,4),se(t,r,e,n,23,4),e+4}function Je(t,r,e,n,o){return o||Fe(t,0,e,8),se(t,r,e,n,52,8),e+8}ge.prototype.slice=function(t,r){var e,n=this.length;if((t=~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),(r=void 0===r?n:~~r)<0?(r+=n)<0&&(r=0):r>n&&(r=n),r0&&(o*=256);)n+=this[t+--r]*o;return n},ge.prototype.readUInt8=function(t,r){return r||ke(t,1,this.length),this[t]},ge.prototype.readUInt16LE=function(t,r){return r||ke(t,2,this.length),this[t]|this[t+1]<<8},ge.prototype.readUInt16BE=function(t,r){return r||ke(t,2,this.length),this[t]<<8|this[t+1]},ge.prototype.readUInt32LE=function(t,r){return r||ke(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},ge.prototype.readUInt32BE=function(t,r){return r||ke(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},ge.prototype.readIntLE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=this[t],o=1,i=0;++i=(o*=128)&&(n-=Math.pow(2,8*r)),n},ge.prototype.readIntBE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=r,o=1,i=this[t+--n];n>0&&(o*=256);)i+=this[t+--n]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*r)),i},ge.prototype.readInt8=function(t,r){return r||ke(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},ge.prototype.readInt16LE=function(t,r){r||ke(t,2,this.length);var e=this[t]|this[t+1]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt16BE=function(t,r){r||ke(t,2,this.length);var e=this[t+1]|this[t]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt32LE=function(t,r){return r||ke(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},ge.prototype.readInt32BE=function(t,r){return r||ke(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},ge.prototype.readFloatLE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!0,23,4)},ge.prototype.readFloatBE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!1,23,4)},ge.prototype.readDoubleLE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!0,52,8)},ge.prototype.readDoubleBE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!1,52,8)},ge.prototype.writeUIntLE=function(t,r,e,n){(t=+t,r|=0,e|=0,n)||De(this,t,r,e,Math.pow(2,8*e)-1,0);var o=1,i=0;for(this[r]=255&t;++i=0&&(i*=256);)this[r+o]=t/i&255;return r+e},ge.prototype.writeUInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,255,0),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[r]=255&t,r+1},ge.prototype.writeUInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeUInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeUInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r+3]=t>>>24,this[r+2]=t>>>16,this[r+1]=t>>>8,this[r]=255&t):ze(this,t,r,!0),r+4},ge.prototype.writeUInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeIntLE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=0,u=1,a=0;for(this[r]=255&t;++i>0)-a&255;return r+e},ge.prototype.writeIntBE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=e-1,u=1,a=0;for(this[r+i]=255&t;--i>=0&&(u*=256);)t<0&&0===a&&0!==this[r+i+1]&&(a=1),this[r+i]=(t/u>>0)-a&255;return r+e},ge.prototype.writeInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,127,-128),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[r]=255&t,r+1},ge.prototype.writeInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8,this[r+2]=t>>>16,this[r+3]=t>>>24):ze(this,t,r,!0),r+4},ge.prototype.writeInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeFloatLE=function(t,r,e){return qe(this,t,r,!0,e)},ge.prototype.writeFloatBE=function(t,r,e){return qe(this,t,r,!1,e)},ge.prototype.writeDoubleLE=function(t,r,e){return Je(this,t,r,!0,e)},ge.prototype.writeDoubleBE=function(t,r,e){return Je(this,t,r,!1,e)},ge.prototype.copy=function(t,r,e,n){if(e||(e=0),n||0===n||(n=this.length),r>=t.length&&(r=t.length),r||(r=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-r=0;--o)t[o+r]=this[o+e];else if(i<1e3||!ge.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,e=void 0===e?this.length:e>>>0,t||(t=0),"number"==typeof t)for(i=r;i55295&&e<57344){if(!o){if(e>56319){(r-=3)>-1&&i.push(239,191,189);continue}if(u+1===n){(r-=3)>-1&&i.push(239,191,189);continue}o=e;continue}if(e<56320){(r-=3)>-1&&i.push(239,191,189),o=e;continue}e=65536+(o-55296<<10|e-56320)}else o&&(r-=3)>-1&&i.push(239,191,189);if(o=null,e<128){if((r-=1)<0)break;i.push(e)}else if(e<2048){if((r-=2)<0)break;i.push(e>>6|192,63&e|128)}else if(e<65536){if((r-=3)<0)break;i.push(e>>12|224,e>>6&63|128,63&e|128)}else{if(!(e<1114112))throw new Error("Invalid code point");if((r-=4)<0)break;i.push(e>>18|240,e>>12&63|128,e>>6&63|128,63&e|128)}}return i}function Ve(t){return function(t){var r,e,n,o,i,u;oe||ie();var a=t.length;if(a%4>0)throw new Error("Invalid string. Length must be a multiple of 4");i="="===t[a-2]?2:"="===t[a-1]?1:0,u=new ne(3*a/4-i),n=i>0?a-4:a;var f=0;for(r=0,e=0;r>16&255,u[f++]=o>>8&255,u[f++]=255&o;return 2===i?(o=ee[t.charCodeAt(r)]<<2|ee[t.charCodeAt(r+1)]>>4,u[f++]=255&o):1===i&&(o=ee[t.charCodeAt(r)]<<10|ee[t.charCodeAt(r+1)]<<4|ee[t.charCodeAt(r+2)]>>2,u[f++]=o>>8&255,u[f++]=255&o),u}(function(t){if((t=function(t){if(t.trim)return t.trim();return t.replace(/^\s+|\s+$/g,"")}(t).replace($e,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function He(t,r,e,n){for(var o=0;o=r.length||o>=t.length);++o)r[o+e]=t[o];return o}function We(t){return null!=t&&(!!t._isBuffer||Ze(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&Ze(t.slice(0,0))}(t))}function Ze(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}var Ke=function(t,r){if(r instanceof Error){var e={};return Object.getOwnPropertyNames(r).forEach((function(t){e[t]=r[t]})),e}return r};var Xe=function(t,r){try{var e=t.headers.accept.split(",");return r?e.filter((function(t){return t===r})):e}catch(t){return[]}},tn=function(t,r){return!!Xe(t,r).length},rn=function(t,r){return t.path===r.jsonqlPath};exports.VERSION="1.2.2",exports.buff=function(t,r){return void 0===r&&(r="base64"),We(t)?t:new ge.from(t,r)},exports.cacheBurst=Yr,exports.cacheBurstUrl=function(t){return Cr(t,Yr())},exports.chainFns=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},exports.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):xr(t,e)}))}))}),Promise.resolve(!1===r?[]:j(r)?r:{}))},exports.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("acknowledge_reply",t,r,e)},exports.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},exports.createMutation=Jr,exports.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Jr(t,r,e,n))},exports.createQuery=qr,exports.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},exports.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("emit_reply",t,r,e)},exports.createWsReply=Xr,exports.dasherize=Ir,exports.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ur("Unknown "+r+" to extract argument from!")}},exports.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Tr(e,r);return n}catch(t){throw new Tr(e,t)}},exports.extractSocketPart=Br,exports.extractWsPayload=function(t,r){void 0===r&&(r=Z);try{var e,n=W(t);if(!1!==(e=te(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ur("payload can not decoded",t)}catch(t){return r("error",t)}},exports.findFromContract=function(t,e,n){return!!(n[t]&&n[t][e]&&n[t][e].file&&r.existsSync(n[t][e].file))&&n[t][e].file},exports.formatPayload=Lr,exports.getCallMethod=function(t){switch(!0){case t===Rr[0]:return"query";case t===Rr[1]:return"mutation";default:return!1}},exports.getConfigValue=function(t,r){return r&&j(r)&&t in r?r[t]:void 0},exports.getDocLen=function(t){return ge.byteLength(t,"utf8")},exports.getMutationFromArgs=Qr,exports.getMutationFromPayload=function(t){var r=Gr(t,Qr);if(!1!==r)return r;throw new Sr("[getMutationArgs] Payload is malformed!",t)},exports.getNamespace=Wr,exports.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},exports.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Wr(t),o=e?Hr(r):function(t,r){var e,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},exports.getPathToFn=function(t,n,o){var i=o.resolverDir,u=Ir(t),a=[];o.contract&&o.contract[n]&&o.contract[n].path&&a.push(o.contract[n].path),a.push(e.join(i,n,u,[Or,Pr].join("."))),a.push(e.join(i,n,[u,Pr].join(".")));for(var f=a.length,s=0;s=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var i=Array(o);++n-1;);return e}(o,i),function(t,r){for(var e=t.length;e--&&U(r,t[e],0)>-1;);return e}(o,i)+1).join("")}var G=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return n(t)?t:[t]},V=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},H=function(t,r){try{var e=Object.keys(t);return G(e,r)}catch(t){return!1}},W=function(t){return V("string"==typeof t?t:JSON.stringify(t))},Z=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function X(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var tt=Array.prototype.splice;function rt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},rt.prototype.set=function(t,r){var e=this.__data__,n=X(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function nt(t){if(!et(t))return!1;var r=y(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var ot,it=a["__core-js_shared__"],ut=(ot=/[^.]+$/.exec(it&&it.keys&&it.keys.IE_PROTO||""))?"Symbol(src)_1."+ot:"";var at=Function.prototype.toString;var ft=/^\[object .+?Constructor\]$/,st=Function.prototype,ct=Object.prototype,ht=st.toString,pt=ct.hasOwnProperty,lt=RegExp("^"+ht.call(pt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function gt(t){return!(!et(t)||function(t){return!!ut&&ut in t}(t))&&(nt(t)?lt:ft).test(function(t){if(null!=t){try{return at.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function yt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return gt(e)?e:void 0}var vt=yt(a,"Map"),dt=yt(Object,"create");var _t=Object.prototype.hasOwnProperty;var bt=Object.prototype.hasOwnProperty;function wt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Jt(t.length)&&!nt(t)}var Gt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Qt=Gt&&"object"==typeof module&&module&&!module.nodeType&&module,Vt=Qt&&Qt.exports===Gt?a.Buffer:void 0,Ht=(Vt?Vt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Zt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Kt=Zt&&"object"==typeof module&&module&&!module.nodeType&&module,Xt=Kt&&Kt.exports===Zt&&i.process,tr=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Xt&&Xt.binding&&Xt.binding("util")}catch(t){}}(),rr=tr&&tr.isTypedArray,er=rr?function(t){return function(r){return t(r)}}(rr):function(t){return b(t)&&Jt(t.length)&&!!Wt[y(t)]};function nr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var or=Object.prototype.hasOwnProperty;function ir(t,r,e){var n=t[r];or.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||jt(t,r,e)}var ur=/^(?:0|[1-9]\d*)$/;function ar(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&ur.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(br);function Ar(t,r){return mr(function(t,r,e){return r=_r(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,i=_r(n.length-r,0),u=Array(i);++o1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=Er.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!et(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ar(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e>18&63]+re[o>>12&63]+re[o>>6&63]+re[63&o]);return i.join("")}function ae(t){var r;oe||ie();for(var e=t.length,n=e%3,o="",i=[],u=0,a=e-n;ua?a:u+16383));return 1===n?(r=t[e-1],o+=re[r>>2],o+=re[r<<4&63],o+="=="):2===n&&(r=(t[e-2]<<8)+t[e-1],o+=re[r>>10],o+=re[r>>4&63],o+=re[r<<2&63],o+="="),i.push(o),i.join("")}function fe(t,r,e,n,o){var i,u,a=8*o-n-1,f=(1<>1,c=-7,h=e?o-1:0,p=e?-1:1,l=t[r+h];for(h+=p,i=l&(1<<-c)-1,l>>=-c,c+=a;c>0;i=256*i+t[r+h],h+=p,c-=8);for(u=i&(1<<-c)-1,i>>=-c,c+=n;c>0;u=256*u+t[r+h],h+=p,c-=8);if(0===i)i=1-s;else{if(i===f)return u?NaN:1/0*(l?-1:1);u+=Math.pow(2,n),i-=s}return(l?-1:1)*u*Math.pow(2,i-n)}function se(t,r,e,n,o,i){var u,a,f,s=8*i-o-1,c=(1<>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,l=n?0:i-1,g=n?1:-1,y=r<0||0===r&&1/r<0?1:0;for(r=Math.abs(r),isNaN(r)||r===1/0?(a=isNaN(r)?1:0,u=c):(u=Math.floor(Math.log(r)/Math.LN2),r*(f=Math.pow(2,-u))<1&&(u--,f*=2),(r+=u+h>=1?p/f:p*Math.pow(2,1-h))*f>=2&&(u++,f/=2),u+h>=c?(a=0,u=c):u+h>=1?(a=(r*f-1)*Math.pow(2,o),u+=h):(a=r*Math.pow(2,h-1)*Math.pow(2,o),u=0));o>=8;t[e+l]=255&a,l+=g,a/=256,o-=8);for(u=u<0;t[e+l]=255&u,l+=g,u/=256,s-=8);t[e+l-g]|=128*y}var ce={}.toString,he=Array.isArray||function(t){return"[object Array]"==ce.call(t)};function pe(){return ge.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function le(t,r){if(pe()=pe())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+pe().toString(16)+" bytes");return 0|t}function we(t){return!(null==t||!t._isBuffer)}function me(t,r){if(we(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var e=t.length;if(0===e)return 0;for(var n=!1;;)switch(r){case"ascii":case"latin1":case"binary":return e;case"utf8":case"utf-8":case void 0:return Qe(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*e;case"hex":return e>>>1;case"base64":return Ve(t).length;default:if(n)return Qe(t).length;r=(""+r).toLowerCase(),n=!0}}function Ae(t,r,e){var n=!1;if((void 0===r||r<0)&&(r=0),r>this.length)return"";if((void 0===e||e>this.length)&&(e=this.length),e<=0)return"";if((e>>>=0)<=(r>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return Ye(this,r,e);case"utf8":case"utf-8":return Ne(this,r,e);case"ascii":return Ie(this,r,e);case"latin1":case"binary":return Ce(this,r,e);case"base64":return Be(this,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Me(this,r,e);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function Ee(t,r,e){var n=t[r];t[r]=t[e],t[e]=n}function xe(t,r,e,n,o){if(0===t.length)return-1;if("string"==typeof e?(n=e,e=0):e>2147483647?e=2147483647:e<-2147483648&&(e=-2147483648),e=+e,isNaN(e)&&(e=o?0:t.length-1),e<0&&(e=t.length+e),e>=t.length){if(o)return-1;e=t.length-1}else if(e<0){if(!o)return-1;e=0}if("string"==typeof r&&(r=ge.from(r,n)),we(r))return 0===r.length?-1:je(t,r,e,n,o);if("number"==typeof r)return r&=255,ge.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,r,e):Uint8Array.prototype.lastIndexOf.call(t,r,e):je(t,[r],e,n,o);throw new TypeError("val must be string, number or Buffer")}function je(t,r,e,n,o){var i,u=1,a=t.length,f=r.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||r.length<2)return-1;u=2,a/=2,f/=2,e/=2}function s(t,r){return 1===u?t[r]:t.readUInt16BE(r*u)}if(o){var c=-1;for(i=e;ia&&(e=a-f),i=e;i>=0;i--){for(var h=!0,p=0;po&&(n=o):n=o;var i=r.length;if(i%2!=0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var u=0;u>8,o=e%256,i.push(o),i.push(n);return i}(r,t.length-e),t,e,n)}function Be(t,r,e){return 0===r&&e===t.length?ae(t):ae(t.slice(r,e))}function Ne(t,r,e){e=Math.min(t.length,e);for(var n=[],o=r;o239?4:s>223?3:s>191?2:1;if(o+h<=e)switch(h){case 1:s<128&&(c=s);break;case 2:128==(192&(i=t[o+1]))&&(f=(31&s)<<6|63&i)>127&&(c=f);break;case 3:i=t[o+1],u=t[o+2],128==(192&i)&&128==(192&u)&&(f=(15&s)<<12|(63&i)<<6|63&u)>2047&&(f<55296||f>57343)&&(c=f);break;case 4:i=t[o+1],u=t[o+2],a=t[o+3],128==(192&i)&&128==(192&u)&&128==(192&a)&&(f=(15&s)<<18|(63&i)<<12|(63&u)<<6|63&a)>65535&&f<1114112&&(c=f)}null===c?(c=65533,h=1):c>65535&&(c-=65536,n.push(c>>>10&1023|55296),c=56320|1023&c),n.push(c),o+=h}return function(t){var r=t.length;if(r<=4096)return String.fromCharCode.apply(String,t);var e="",n=0;for(;n0&&(t=this.toString("hex",0,50).match(/.{2}/g).join(" "),this.length>50&&(t+=" ... ")),""},ge.prototype.compare=function(t,r,e,n,o){if(!we(t))throw new TypeError("Argument must be a Buffer");if(void 0===r&&(r=0),void 0===e&&(e=t?t.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),r<0||e>t.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&r>=e)return 0;if(n>=o)return-1;if(r>=e)return 1;if(this===t)return 0;for(var i=(o>>>=0)-(n>>>=0),u=(e>>>=0)-(r>>>=0),a=Math.min(i,u),f=this.slice(n,o),s=t.slice(r,e),c=0;co)&&(e=o),t.length>0&&(e<0||r<0)||r>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return Pe(this,t,r,e);case"utf8":case"utf-8":return Re(this,t,r,e);case"ascii":return Oe(this,t,r,e);case"latin1":case"binary":return Te(this,t,r,e);case"base64":return Se(this,t,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Ue(this,t,r,e);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},ge.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Ie(t,r,e){var n="";e=Math.min(t.length,e);for(var o=r;on)&&(e=n);for(var o="",i=r;ie)throw new RangeError("Trying to access beyond buffer length")}function De(t,r,e,n,o,i){if(!we(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(r>o||rt.length)throw new RangeError("Index out of range")}function Le(t,r,e,n){r<0&&(r=65535+r+1);for(var o=0,i=Math.min(t.length-e,2);o>>8*(n?o:1-o)}function ze(t,r,e,n){r<0&&(r=4294967295+r+1);for(var o=0,i=Math.min(t.length-e,4);o>>8*(n?o:3-o)&255}function Fe(t,r,e,n,o,i){if(e+n>t.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function qe(t,r,e,n,o){return o||Fe(t,0,e,4),se(t,r,e,n,23,4),e+4}function Je(t,r,e,n,o){return o||Fe(t,0,e,8),se(t,r,e,n,52,8),e+8}ge.prototype.slice=function(t,r){var e,n=this.length;if((t=~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),(r=void 0===r?n:~~r)<0?(r+=n)<0&&(r=0):r>n&&(r=n),r0&&(o*=256);)n+=this[t+--r]*o;return n},ge.prototype.readUInt8=function(t,r){return r||ke(t,1,this.length),this[t]},ge.prototype.readUInt16LE=function(t,r){return r||ke(t,2,this.length),this[t]|this[t+1]<<8},ge.prototype.readUInt16BE=function(t,r){return r||ke(t,2,this.length),this[t]<<8|this[t+1]},ge.prototype.readUInt32LE=function(t,r){return r||ke(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},ge.prototype.readUInt32BE=function(t,r){return r||ke(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},ge.prototype.readIntLE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=this[t],o=1,i=0;++i=(o*=128)&&(n-=Math.pow(2,8*r)),n},ge.prototype.readIntBE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=r,o=1,i=this[t+--n];n>0&&(o*=256);)i+=this[t+--n]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*r)),i},ge.prototype.readInt8=function(t,r){return r||ke(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},ge.prototype.readInt16LE=function(t,r){r||ke(t,2,this.length);var e=this[t]|this[t+1]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt16BE=function(t,r){r||ke(t,2,this.length);var e=this[t+1]|this[t]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt32LE=function(t,r){return r||ke(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},ge.prototype.readInt32BE=function(t,r){return r||ke(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},ge.prototype.readFloatLE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!0,23,4)},ge.prototype.readFloatBE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!1,23,4)},ge.prototype.readDoubleLE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!0,52,8)},ge.prototype.readDoubleBE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!1,52,8)},ge.prototype.writeUIntLE=function(t,r,e,n){(t=+t,r|=0,e|=0,n)||De(this,t,r,e,Math.pow(2,8*e)-1,0);var o=1,i=0;for(this[r]=255&t;++i=0&&(i*=256);)this[r+o]=t/i&255;return r+e},ge.prototype.writeUInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,255,0),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[r]=255&t,r+1},ge.prototype.writeUInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeUInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeUInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r+3]=t>>>24,this[r+2]=t>>>16,this[r+1]=t>>>8,this[r]=255&t):ze(this,t,r,!0),r+4},ge.prototype.writeUInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeIntLE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=0,u=1,a=0;for(this[r]=255&t;++i>0)-a&255;return r+e},ge.prototype.writeIntBE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=e-1,u=1,a=0;for(this[r+i]=255&t;--i>=0&&(u*=256);)t<0&&0===a&&0!==this[r+i+1]&&(a=1),this[r+i]=(t/u>>0)-a&255;return r+e},ge.prototype.writeInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,127,-128),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[r]=255&t,r+1},ge.prototype.writeInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8,this[r+2]=t>>>16,this[r+3]=t>>>24):ze(this,t,r,!0),r+4},ge.prototype.writeInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeFloatLE=function(t,r,e){return qe(this,t,r,!0,e)},ge.prototype.writeFloatBE=function(t,r,e){return qe(this,t,r,!1,e)},ge.prototype.writeDoubleLE=function(t,r,e){return Je(this,t,r,!0,e)},ge.prototype.writeDoubleBE=function(t,r,e){return Je(this,t,r,!1,e)},ge.prototype.copy=function(t,r,e,n){if(e||(e=0),n||0===n||(n=this.length),r>=t.length&&(r=t.length),r||(r=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-r=0;--o)t[o+r]=this[o+e];else if(i<1e3||!ge.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,e=void 0===e?this.length:e>>>0,t||(t=0),"number"==typeof t)for(i=r;i55295&&e<57344){if(!o){if(e>56319){(r-=3)>-1&&i.push(239,191,189);continue}if(u+1===n){(r-=3)>-1&&i.push(239,191,189);continue}o=e;continue}if(e<56320){(r-=3)>-1&&i.push(239,191,189),o=e;continue}e=65536+(o-55296<<10|e-56320)}else o&&(r-=3)>-1&&i.push(239,191,189);if(o=null,e<128){if((r-=1)<0)break;i.push(e)}else if(e<2048){if((r-=2)<0)break;i.push(e>>6|192,63&e|128)}else if(e<65536){if((r-=3)<0)break;i.push(e>>12|224,e>>6&63|128,63&e|128)}else{if(!(e<1114112))throw new Error("Invalid code point");if((r-=4)<0)break;i.push(e>>18|240,e>>12&63|128,e>>6&63|128,63&e|128)}}return i}function Ve(t){return function(t){var r,e,n,o,i,u;oe||ie();var a=t.length;if(a%4>0)throw new Error("Invalid string. Length must be a multiple of 4");i="="===t[a-2]?2:"="===t[a-1]?1:0,u=new ne(3*a/4-i),n=i>0?a-4:a;var f=0;for(r=0,e=0;r>16&255,u[f++]=o>>8&255,u[f++]=255&o;return 2===i?(o=ee[t.charCodeAt(r)]<<2|ee[t.charCodeAt(r+1)]>>4,u[f++]=255&o):1===i&&(o=ee[t.charCodeAt(r)]<<10|ee[t.charCodeAt(r+1)]<<4|ee[t.charCodeAt(r+2)]>>2,u[f++]=o>>8&255,u[f++]=255&o),u}(function(t){if((t=function(t){if(t.trim)return t.trim();return t.replace(/^\s+|\s+$/g,"")}(t).replace($e,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function He(t,r,e,n){for(var o=0;o=r.length||o>=t.length);++o)r[o+e]=t[o];return o}function We(t){return null!=t&&(!!t._isBuffer||Ze(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&Ze(t.slice(0,0))}(t))}function Ze(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}var Ke=function(t,r){if(r instanceof Error){var e={};return Object.getOwnPropertyNames(r).forEach((function(t){e[t]=r[t]})),e}return r};var Xe=function(t,r){try{var e=t.headers.accept.split(",");return r?e.filter((function(t){return t===r})):e}catch(t){return[]}},tn=function(t,r){return!!Xe(t,r).length},rn=function(t,r){return t.path===r.jsonqlPath};exports.VERSION="1.2.3",exports.assign=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return console.info("assing",t),Reflect.apply(Object.assign,Object,t)},exports.buff=function(t,r){return void 0===r&&(r="base64"),We(t)?t:new ge.from(t,r)},exports.cacheBurst=Yr,exports.cacheBurstUrl=function(t){return Cr(t,Yr())},exports.chainFns=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},exports.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):xr(t,e)}))}))}),Promise.resolve(!1===r?[]:j(r)?r:{}))},exports.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("acknowledge_reply",t,r,e)},exports.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},exports.createMutation=Jr,exports.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Jr(t,r,e,n))},exports.createQuery=qr,exports.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},exports.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("emit_reply",t,r,e)},exports.createWsReply=Xr,exports.dasherize=Ir,exports.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ur("Unknown "+r+" to extract argument from!")}},exports.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Tr(e,r);return n}catch(t){throw new Tr(e,t)}},exports.extractSocketPart=Br,exports.extractWsPayload=function(t,r){void 0===r&&(r=Z);try{var e,n=W(t);if(!1!==(e=te(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ur("payload can not decoded",t)}catch(t){return r("error",t)}},exports.findFromContract=function(t,e,n){return!!(n[t]&&n[t][e]&&n[t][e].file&&r.existsSync(n[t][e].file))&&n[t][e].file},exports.formatPayload=Lr,exports.getCallMethod=function(t){switch(!0){case t===Rr[0]:return"query";case t===Rr[1]:return"mutation";default:return!1}},exports.getConfigValue=function(t,r){return r&&j(r)&&t in r?r[t]:void 0},exports.getDocLen=function(t){return ge.byteLength(t,"utf8")},exports.getMutationFromArgs=Qr,exports.getMutationFromPayload=function(t){var r=Gr(t,Qr);if(!1!==r)return r;throw new Sr("[getMutationArgs] Payload is malformed!",t)},exports.getNamespace=Wr,exports.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},exports.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Wr(t),o=e?Hr(r):function(t,r){var e,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},exports.getPathToFn=function(t,n,o){var i=o.resolverDir,u=Ir(t),a=[];o.contract&&o.contract[n]&&o.contract[n].path&&a.push(o.contract[n].path),a.push(e.join(i,n,u,[Or,Pr].join("."))),a.push(e.join(i,n,[u,Pr].join(".")));for(var f=a.length,s=0;s { console.error(`Expect to be Function type! Got ${typeof prop}`) } +/** + * Shorthand method for Object.assign + * @param {array} args + * @return {object} merge together object by key + */ +export const assign = (...args) => Reflect.apply(Object.assign, Object, args) + + // generic placeholder function export const nil = () => false diff --git a/packages/utils/tests/construct.test.js b/packages/utils/tests/construct.test.js index 569e9007..e7752699 100644 --- a/packages/utils/tests/construct.test.js +++ b/packages/utils/tests/construct.test.js @@ -1,6 +1,7 @@ // this is ported back from jsonql-params-validator const test = require('ava') -const { isContract, isObjectHasKey } = require('../main') +const { isContract, isObjectHasKey, assign } = require('../main') +const debug = require('debug')('jsonql-utils:construct') test("It should able to check if an object is contract or not", t => { @@ -22,3 +23,22 @@ test("Test isObjectHasKey is exported or not", t => { t.false(isObjectHasKey(client, 'auth')) }) + +test(`Testing the assign method`, t => { + const keys = ['a', 'b', 'c'] + const result = [1,2,3] + .map((num, i) => { + debug(i, num) + return { + [keys[i]]: num + } + }) + .reduce(assign, {}) + + debug('assign result', result) + + t.is(result['a'], 1) + t.is(result['b'], 2) + t.is(result['c'], 3) + +}) -- Gitee From 07f3643729770165763979aea2ad51a5246564d1 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 21:35:22 +0800 Subject: [PATCH 35/66] jsonql-ws-server-core 0.7.9 --- packages/utils/browser.js | 2 +- packages/utils/main.js | 2 +- packages/ws-server-core/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/utils/browser.js b/packages/utils/browser.js index 0448b2d8..41c691d7 100644 --- a/packages/utils/browser.js +++ b/packages/utils/browser.js @@ -1,2 +1,2 @@ -!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t=t||self).jsonqlUtils={})}(this,(function(t){"use strict";var r=Array.isArray,e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},n="object"==typeof e&&e&&e.Object===Object&&e,o="object"==typeof self&&self&&self.Object===Object&&self,u=n||o||Function("return this")(),i=u.Symbol,a=Object.prototype,c=a.hasOwnProperty,f=a.toString,s=i?i.toStringTag:void 0;var l=Object.prototype.toString;var p=i?i.toStringTag:void 0;function v(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":p&&p in Object(t)?function(t){var r=c.call(t,s),e=t[s];try{t[s]=void 0;var n=!0}catch(t){}var o=f.call(t);return n&&(r?t[s]=e:delete t[s]),o}(t):function(t){return l.call(t)}(t)}var d,y,h=(d=Object.getPrototypeOf,y=Object,function(t){return d(y(t))});function g(t){return null!=t&&"object"==typeof t}var _=Function.prototype,b=Object.prototype,j=_.toString,m=b.hasOwnProperty,O=j.call(Object);function w(t){if(!g(t)||"[object Object]"!=v(t))return!1;var r=h(t);if(null===r)return!0;var e=m.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&j.call(e)==O}var S=i?i.prototype:void 0,P=S?S.toString:void 0;function N(t){if("string"==typeof t)return t;if(r(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var u=Array(o);++n-1;);return e}(o,u),function(t,r){for(var e=t.length;e--&&E(r,t[e],0)>-1;);return e}(o,u)+1).join("")}var I=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return r(t)?t:[t]},L=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},V=function(t,r){try{var e=Object.keys(t);return I(e,r)}catch(t){return!1}},W=function(t){return L("string"==typeof t?t:JSON.stringify(t))},H=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function Z(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var X=Array.prototype.splice;function Y(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},Y.prototype.set=function(t,r){var e=this.__data__,n=Z(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function rt(t){if(!tt(t))return!1;var r=v(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var et,nt=u["__core-js_shared__"],ot=(et=/[^.]+$/.exec(nt&&nt.keys&&nt.keys.IE_PROTO||""))?"Symbol(src)_1."+et:"";var ut=Function.prototype.toString;var it=/^\[object .+?Constructor\]$/,at=Function.prototype,ct=Object.prototype,ft=at.toString,st=ct.hasOwnProperty,lt=RegExp("^"+ft.call(st).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pt(t){return!(!tt(t)||function(t){return!!ot&&ot in t}(t))&&(rt(t)?lt:it).test(function(t){if(null!=t){try{return ut.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function vt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pt(e)?e:void 0}var dt=vt(u,"Map"),yt=vt(Object,"create");var ht=Object.prototype.hasOwnProperty;var gt=Object.prototype.hasOwnProperty;function _t(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Gt(t.length)&&!rt(t)}var It="object"==typeof t&&t&&!t.nodeType&&t,Qt=It&&"object"==typeof module&&module&&!module.nodeType&&module,Lt=Qt&&Qt.exports===It?u.Buffer:void 0,Vt=(Lt?Lt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Ht="object"==typeof t&&t&&!t.nodeType&&t,Kt=Ht&&"object"==typeof module&&module&&!module.nodeType&&module,Zt=Kt&&Kt.exports===Ht&&n.process,Xt=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Zt&&Zt.binding&&Zt.binding("util")}catch(t){}}(),Yt=Xt&&Xt.isTypedArray,tr=Yt?function(t){return function(r){return t(r)}}(Yt):function(t){return g(t)&&Gt(t.length)&&!!Wt[v(t)]};function rr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var er=Object.prototype.hasOwnProperty;function nr(t,r,e){var n=t[r];er.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||wt(t,r,e)}var or=/^(?:0|[1-9]\d*)$/;function ur(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&or.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(gr);function jr(t,r){return br(function(t,r,e){return r=hr(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,u=hr(n.length-r,0),i=Array(u);++o1?r[n-1]:void 0,u=n>2?r[2]:void 0;for(o=mr.length>3&&"function"==typeof o?(n--,o):void 0,u&&function(t,r,e){if(!tt(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ur(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],u)&&(o=n<3?void 0:o,n=1),t=Object(t);++e0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},t.chainProcessPromises=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return t.then((function(t){return r(t)}))}),Reflect.apply(t,null,e))}},t.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):Or(t,e)}))}))}),Promise.resolve(!1===r?[]:w(r)?r:{}))},t.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("acknowledge_reply",t,r,e)},t.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},t.createMutation=Ur,t.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Ur(t,r,e,n))},t.createQuery=qr,t.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},t.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("emit_reply",t,r,e)},t.createWsReply=Wr,t.dasherize=function(t){return $(t).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},t.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ar("Unknown "+r+" to extract argument from!")}},t.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Pr(e,r);return n}catch(t){throw new Pr(e,t)}},t.extractSocketPart=Tr,t.extractWsPayload=function(t,r){void 0===r&&(r=H);try{var e,n=W(t);if(!1!==(e=Hr(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ar("payload can not decoded",t)}catch(t){return r("error",t)}},t.formatPayload=Jr,t.getCallMethod=function(t){switch(!0){case t===Sr[0]:return"query";case t===Sr[1]:return"mutation";default:return!1}},t.getConfigValue=function(t,r){return r&&w(r)&&t in r?r[t]:void 0},t.getLogger=function(t){var r=[t];return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];try{window&&window.JSONQL_DEBUG&&Reflect.apply(console.info,console,r.concat(t))}catch(t){}}},t.getMutationFromArgs=Gr,t.getMutationFromPayload=function(t){var r=Dr(t,Gr);if(!1!==r)return r;throw new Nr("[getMutationArgs] Payload is malformed!",t)},t.getNamespace=Qr,t.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},t.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Qr(t),o=e?Ir(r):function(t,r){var e,n={};for(var o in t){var u=t[o];n[o]=u}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},t.getPrivateNamespace=function(t){return t.length>1&&t[0]},t.getQueryFromArgs=Br,t.getQueryFromPayload=function(t){var r=Dr(t,Br);if(!1!==r)return r;throw new Nr("[getQueryArgs] Payload is malformed!",t)},t.getRegex=function(t){switch(!0){case!0===Lr(t):return t;case!0===kr(t):return new RegExp(t);default:return!1}},t.getResolverFromPayload=Mr,t.groupByNamespace=Ir,t.inArray=I,t.injectToFn=function(t,r,e,n){void 0===n&&(n=!1);var o=wr(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t},t.isContract=function(t){return!!function(t){return w(t)&&(V(t,"query")||V(t,"mutation")||V(t,"socket"))}(t)&&t},t.isFunc=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},t.isJsonqlErrorObj=$r,t.isNotEmpty=function(t){return void 0!==t&&!1!==t&&null!==t&&""!==$(t)},t.isObjectHasKey=V,t.isRegExp=Lr,t.isWsReply=Hr,t.logger=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];try{window&&window.DEBUG&&Reflect.apply(console.log,console,t)}catch(t){}},t.nil=H,t.objDefineProps=function(t,r,e,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,r)&&Object.defineProperty(t,r,{set:e,get:null===n?function(){return null}:n}),t},t.objHasProp=wr,t.packError=function(t,r,e,n){var o;void 0===r&&(r="JsonqlError"),void 0===e&&(e=0),void 0===n&&(n="");var u={detail:t,className:r,statusCode:e,message:n};return JSON.stringify(((o={}).error=$r(t)||u,o.TS=[Er()],o))},t.packResult=function(t,e){void 0===e&&(e=!1);var n={};return n.data=t,e&&r(e)&&(e.push(Er()),n.TS=e),JSON.stringify(n)},t.parseJson=L,t.resultHandler=function(t){return V(t,"data")&&!V(t,"error")?t.data:t},t.timestamp=Er,t.toArray=Q,t.toJson=W,t.toPayload=Fr,t.urlParams=xr,Object.defineProperty(t,"__esModule",{value:!0})})); +!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t=t||self).jsonqlUtils={})}(this,(function(t){"use strict";var r=Array.isArray,e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},n="object"==typeof e&&e&&e.Object===Object&&e,o="object"==typeof self&&self&&self.Object===Object&&self,u=n||o||Function("return this")(),i=u.Symbol,a=Object.prototype,c=a.hasOwnProperty,f=a.toString,s=i?i.toStringTag:void 0;var l=Object.prototype.toString;var p=i?i.toStringTag:void 0;function v(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":p&&p in Object(t)?function(t){var r=c.call(t,s),e=t[s];try{t[s]=void 0;var n=!0}catch(t){}var o=f.call(t);return n&&(r?t[s]=e:delete t[s]),o}(t):function(t){return l.call(t)}(t)}var d,y,h=(d=Object.getPrototypeOf,y=Object,function(t){return d(y(t))});function g(t){return null!=t&&"object"==typeof t}var _=Function.prototype,b=Object.prototype,j=_.toString,m=b.hasOwnProperty,O=j.call(Object);function w(t){if(!g(t)||"[object Object]"!=v(t))return!1;var r=h(t);if(null===r)return!0;var e=m.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&j.call(e)==O}var S=i?i.prototype:void 0,P=S?S.toString:void 0;function N(t){if("string"==typeof t)return t;if(r(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var u=Array(o);++n-1;);return e}(o,u),function(t,r){for(var e=t.length;e--&&E(r,t[e],0)>-1;);return e}(o,u)+1).join("")}var I=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return r(t)?t:[t]},L=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},V=function(t,r){try{var e=Object.keys(t);return I(e,r)}catch(t){return!1}},W=function(t){return L("string"==typeof t?t:JSON.stringify(t))},H=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function Z(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var X=Array.prototype.splice;function Y(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},Y.prototype.set=function(t,r){var e=this.__data__,n=Z(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function rt(t){if(!tt(t))return!1;var r=v(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var et,nt=u["__core-js_shared__"],ot=(et=/[^.]+$/.exec(nt&&nt.keys&&nt.keys.IE_PROTO||""))?"Symbol(src)_1."+et:"";var ut=Function.prototype.toString;var it=/^\[object .+?Constructor\]$/,at=Function.prototype,ct=Object.prototype,ft=at.toString,st=ct.hasOwnProperty,lt=RegExp("^"+ft.call(st).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pt(t){return!(!tt(t)||function(t){return!!ot&&ot in t}(t))&&(rt(t)?lt:it).test(function(t){if(null!=t){try{return ut.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function vt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pt(e)?e:void 0}var dt=vt(u,"Map"),yt=vt(Object,"create");var ht=Object.prototype.hasOwnProperty;var gt=Object.prototype.hasOwnProperty;function _t(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Gt(t.length)&&!rt(t)}var It="object"==typeof t&&t&&!t.nodeType&&t,Qt=It&&"object"==typeof module&&module&&!module.nodeType&&module,Lt=Qt&&Qt.exports===It?u.Buffer:void 0,Vt=(Lt?Lt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Ht="object"==typeof t&&t&&!t.nodeType&&t,Kt=Ht&&"object"==typeof module&&module&&!module.nodeType&&module,Zt=Kt&&Kt.exports===Ht&&n.process,Xt=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Zt&&Zt.binding&&Zt.binding("util")}catch(t){}}(),Yt=Xt&&Xt.isTypedArray,tr=Yt?function(t){return function(r){return t(r)}}(Yt):function(t){return g(t)&&Gt(t.length)&&!!Wt[v(t)]};function rr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var er=Object.prototype.hasOwnProperty;function nr(t,r,e){var n=t[r];er.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||wt(t,r,e)}var or=/^(?:0|[1-9]\d*)$/;function ur(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&or.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(gr);function jr(t,r){return br(function(t,r,e){return r=hr(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,u=hr(n.length-r,0),i=Array(u);++o1?r[n-1]:void 0,u=n>2?r[2]:void 0;for(o=mr.length>3&&"function"==typeof o?(n--,o):void 0,u&&function(t,r,e){if(!tt(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ur(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],u)&&(o=n<3?void 0:o,n=1),t=Object(t);++e0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},t.chainProcessPromises=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return t.then((function(t){return r(t)}))}),Reflect.apply(t,null,e))}},t.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):Or(t,e)}))}))}),Promise.resolve(!1===r?[]:w(r)?r:{}))},t.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("acknowledge_reply",t,r,e)},t.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},t.createMutation=Ur,t.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Ur(t,r,e,n))},t.createQuery=qr,t.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},t.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("emit_reply",t,r,e)},t.createWsReply=Wr,t.dasherize=function(t){return $(t).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},t.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ar("Unknown "+r+" to extract argument from!")}},t.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Pr(e,r);return n}catch(t){throw new Pr(e,t)}},t.extractSocketPart=Tr,t.extractWsPayload=function(t,r){void 0===r&&(r=H);try{var e,n=W(t);if(!1!==(e=Hr(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ar("payload can not decoded",t)}catch(t){return r("error",t)}},t.formatPayload=Jr,t.getCallMethod=function(t){switch(!0){case t===Sr[0]:return"query";case t===Sr[1]:return"mutation";default:return!1}},t.getConfigValue=function(t,r){return r&&w(r)&&t in r?r[t]:void 0},t.getLogger=function(t){var r=[t];return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];try{window&&window.JSONQL_DEBUG&&Reflect.apply(console.info,console,r.concat(t))}catch(t){}}},t.getMutationFromArgs=Gr,t.getMutationFromPayload=function(t){var r=Dr(t,Gr);if(!1!==r)return r;throw new Nr("[getMutationArgs] Payload is malformed!",t)},t.getNamespace=Qr,t.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},t.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Qr(t),o=e?Ir(r):function(t,r){var e,n={};for(var o in t){var u=t[o];n[o]=u}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},t.getPrivateNamespace=function(t){return t.length>1&&t[0]},t.getQueryFromArgs=Br,t.getQueryFromPayload=function(t){var r=Dr(t,Br);if(!1!==r)return r;throw new Nr("[getQueryArgs] Payload is malformed!",t)},t.getRegex=function(t){switch(!0){case!0===Lr(t):return t;case!0===kr(t):return new RegExp(t);default:return!1}},t.getResolverFromPayload=Mr,t.groupByNamespace=Ir,t.inArray=I,t.injectToFn=function(t,r,e,n){void 0===n&&(n=!1);var o=wr(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t},t.isContract=function(t){return!!function(t){return w(t)&&(V(t,"query")||V(t,"mutation")||V(t,"socket"))}(t)&&t},t.isFunc=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},t.isJsonqlErrorObj=$r,t.isNotEmpty=function(t){return void 0!==t&&!1!==t&&null!==t&&""!==$(t)},t.isObjectHasKey=V,t.isRegExp=Lr,t.isWsReply=Hr,t.logger=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];try{window&&window.DEBUG&&Reflect.apply(console.log,console,t)}catch(t){}},t.nil=H,t.objDefineProps=function(t,r,e,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,r)&&Object.defineProperty(t,r,{set:e,get:null===n?function(){return null}:n}),t},t.objHasProp=wr,t.packError=function(t,r,e,n){var o;void 0===r&&(r="JsonqlError"),void 0===e&&(e=0),void 0===n&&(n="");var u={detail:t,className:r,statusCode:e,message:n};return JSON.stringify(((o={}).error=$r(t)||u,o.TS=[Er()],o))},t.packResult=function(t,e){void 0===e&&(e=!1);var n={};return n.data=t,e&&r(e)&&(e.push(Er()),n.TS=e),JSON.stringify(n)},t.parseJson=L,t.resultHandler=function(t){return V(t,"data")&&!V(t,"error")?t.data:t},t.timestamp=Er,t.toArray=Q,t.toJson=W,t.toPayload=Fr,t.urlParams=xr,Object.defineProperty(t,"__esModule",{value:!0})})); //# sourceMappingURL=browser.js.map diff --git a/packages/utils/main.js b/packages/utils/main.js index 75d40904..beeba934 100644 --- a/packages/utils/main.js +++ b/packages/utils/main.js @@ -1,2 +1,2 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t,r=(t=require("fs"))&&"object"==typeof t&&"default"in t?t.default:t,e=require("path"),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,u="object"==typeof self&&self&&self.Object===Object&&self,a=i||u||Function("return this")(),f=a.Symbol,s=Object.prototype,c=s.hasOwnProperty,h=s.toString,p=f?f.toStringTag:void 0;var l=Object.prototype.toString;var g=f?f.toStringTag:void 0;function y(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":g&&g in Object(t)?function(t){var r=c.call(t,p),e=t[p];try{t[p]=void 0;var n=!0}catch(t){}var o=h.call(t);return n&&(r?t[p]=e:delete t[p]),o}(t):function(t){return l.call(t)}(t)}var v,d,_=(v=Object.getPrototypeOf,d=Object,function(t){return v(d(t))});function b(t){return null!=t&&"object"==typeof t}var w=Function.prototype,m=Object.prototype,A=w.toString,E=m.hasOwnProperty,x=A.call(Object);function j(t){if(!b(t)||"[object Object]"!=y(t))return!1;var r=_(t);if(null===r)return!0;var e=E.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&A.call(e)==x}var P=f?f.prototype:void 0,R=P?P.toString:void 0;function O(t){if("string"==typeof t)return t;if(n(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var i=Array(o);++n-1;);return e}(o,i),function(t,r){for(var e=t.length;e--&&U(r,t[e],0)>-1;);return e}(o,i)+1).join("")}var G=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return n(t)?t:[t]},V=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},H=function(t,r){try{var e=Object.keys(t);return G(e,r)}catch(t){return!1}},W=function(t){return V("string"==typeof t?t:JSON.stringify(t))},Z=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function X(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var tt=Array.prototype.splice;function rt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},rt.prototype.set=function(t,r){var e=this.__data__,n=X(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function nt(t){if(!et(t))return!1;var r=y(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var ot,it=a["__core-js_shared__"],ut=(ot=/[^.]+$/.exec(it&&it.keys&&it.keys.IE_PROTO||""))?"Symbol(src)_1."+ot:"";var at=Function.prototype.toString;var ft=/^\[object .+?Constructor\]$/,st=Function.prototype,ct=Object.prototype,ht=st.toString,pt=ct.hasOwnProperty,lt=RegExp("^"+ht.call(pt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function gt(t){return!(!et(t)||function(t){return!!ut&&ut in t}(t))&&(nt(t)?lt:ft).test(function(t){if(null!=t){try{return at.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function yt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return gt(e)?e:void 0}var vt=yt(a,"Map"),dt=yt(Object,"create");var _t=Object.prototype.hasOwnProperty;var bt=Object.prototype.hasOwnProperty;function wt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Jt(t.length)&&!nt(t)}var Gt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Qt=Gt&&"object"==typeof module&&module&&!module.nodeType&&module,Vt=Qt&&Qt.exports===Gt?a.Buffer:void 0,Ht=(Vt?Vt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Zt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Kt=Zt&&"object"==typeof module&&module&&!module.nodeType&&module,Xt=Kt&&Kt.exports===Zt&&i.process,tr=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Xt&&Xt.binding&&Xt.binding("util")}catch(t){}}(),rr=tr&&tr.isTypedArray,er=rr?function(t){return function(r){return t(r)}}(rr):function(t){return b(t)&&Jt(t.length)&&!!Wt[y(t)]};function nr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var or=Object.prototype.hasOwnProperty;function ir(t,r,e){var n=t[r];or.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||jt(t,r,e)}var ur=/^(?:0|[1-9]\d*)$/;function ar(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&ur.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(br);function Ar(t,r){return mr(function(t,r,e){return r=_r(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,i=_r(n.length-r,0),u=Array(i);++o1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=Er.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!et(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ar(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e>18&63]+re[o>>12&63]+re[o>>6&63]+re[63&o]);return i.join("")}function ae(t){var r;oe||ie();for(var e=t.length,n=e%3,o="",i=[],u=0,a=e-n;ua?a:u+16383));return 1===n?(r=t[e-1],o+=re[r>>2],o+=re[r<<4&63],o+="=="):2===n&&(r=(t[e-2]<<8)+t[e-1],o+=re[r>>10],o+=re[r>>4&63],o+=re[r<<2&63],o+="="),i.push(o),i.join("")}function fe(t,r,e,n,o){var i,u,a=8*o-n-1,f=(1<>1,c=-7,h=e?o-1:0,p=e?-1:1,l=t[r+h];for(h+=p,i=l&(1<<-c)-1,l>>=-c,c+=a;c>0;i=256*i+t[r+h],h+=p,c-=8);for(u=i&(1<<-c)-1,i>>=-c,c+=n;c>0;u=256*u+t[r+h],h+=p,c-=8);if(0===i)i=1-s;else{if(i===f)return u?NaN:1/0*(l?-1:1);u+=Math.pow(2,n),i-=s}return(l?-1:1)*u*Math.pow(2,i-n)}function se(t,r,e,n,o,i){var u,a,f,s=8*i-o-1,c=(1<>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,l=n?0:i-1,g=n?1:-1,y=r<0||0===r&&1/r<0?1:0;for(r=Math.abs(r),isNaN(r)||r===1/0?(a=isNaN(r)?1:0,u=c):(u=Math.floor(Math.log(r)/Math.LN2),r*(f=Math.pow(2,-u))<1&&(u--,f*=2),(r+=u+h>=1?p/f:p*Math.pow(2,1-h))*f>=2&&(u++,f/=2),u+h>=c?(a=0,u=c):u+h>=1?(a=(r*f-1)*Math.pow(2,o),u+=h):(a=r*Math.pow(2,h-1)*Math.pow(2,o),u=0));o>=8;t[e+l]=255&a,l+=g,a/=256,o-=8);for(u=u<0;t[e+l]=255&u,l+=g,u/=256,s-=8);t[e+l-g]|=128*y}var ce={}.toString,he=Array.isArray||function(t){return"[object Array]"==ce.call(t)};function pe(){return ge.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function le(t,r){if(pe()=pe())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+pe().toString(16)+" bytes");return 0|t}function we(t){return!(null==t||!t._isBuffer)}function me(t,r){if(we(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var e=t.length;if(0===e)return 0;for(var n=!1;;)switch(r){case"ascii":case"latin1":case"binary":return e;case"utf8":case"utf-8":case void 0:return Qe(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*e;case"hex":return e>>>1;case"base64":return Ve(t).length;default:if(n)return Qe(t).length;r=(""+r).toLowerCase(),n=!0}}function Ae(t,r,e){var n=!1;if((void 0===r||r<0)&&(r=0),r>this.length)return"";if((void 0===e||e>this.length)&&(e=this.length),e<=0)return"";if((e>>>=0)<=(r>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return Ye(this,r,e);case"utf8":case"utf-8":return Ne(this,r,e);case"ascii":return Ie(this,r,e);case"latin1":case"binary":return Ce(this,r,e);case"base64":return Be(this,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Me(this,r,e);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function Ee(t,r,e){var n=t[r];t[r]=t[e],t[e]=n}function xe(t,r,e,n,o){if(0===t.length)return-1;if("string"==typeof e?(n=e,e=0):e>2147483647?e=2147483647:e<-2147483648&&(e=-2147483648),e=+e,isNaN(e)&&(e=o?0:t.length-1),e<0&&(e=t.length+e),e>=t.length){if(o)return-1;e=t.length-1}else if(e<0){if(!o)return-1;e=0}if("string"==typeof r&&(r=ge.from(r,n)),we(r))return 0===r.length?-1:je(t,r,e,n,o);if("number"==typeof r)return r&=255,ge.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,r,e):Uint8Array.prototype.lastIndexOf.call(t,r,e):je(t,[r],e,n,o);throw new TypeError("val must be string, number or Buffer")}function je(t,r,e,n,o){var i,u=1,a=t.length,f=r.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||r.length<2)return-1;u=2,a/=2,f/=2,e/=2}function s(t,r){return 1===u?t[r]:t.readUInt16BE(r*u)}if(o){var c=-1;for(i=e;ia&&(e=a-f),i=e;i>=0;i--){for(var h=!0,p=0;po&&(n=o):n=o;var i=r.length;if(i%2!=0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var u=0;u>8,o=e%256,i.push(o),i.push(n);return i}(r,t.length-e),t,e,n)}function Be(t,r,e){return 0===r&&e===t.length?ae(t):ae(t.slice(r,e))}function Ne(t,r,e){e=Math.min(t.length,e);for(var n=[],o=r;o239?4:s>223?3:s>191?2:1;if(o+h<=e)switch(h){case 1:s<128&&(c=s);break;case 2:128==(192&(i=t[o+1]))&&(f=(31&s)<<6|63&i)>127&&(c=f);break;case 3:i=t[o+1],u=t[o+2],128==(192&i)&&128==(192&u)&&(f=(15&s)<<12|(63&i)<<6|63&u)>2047&&(f<55296||f>57343)&&(c=f);break;case 4:i=t[o+1],u=t[o+2],a=t[o+3],128==(192&i)&&128==(192&u)&&128==(192&a)&&(f=(15&s)<<18|(63&i)<<12|(63&u)<<6|63&a)>65535&&f<1114112&&(c=f)}null===c?(c=65533,h=1):c>65535&&(c-=65536,n.push(c>>>10&1023|55296),c=56320|1023&c),n.push(c),o+=h}return function(t){var r=t.length;if(r<=4096)return String.fromCharCode.apply(String,t);var e="",n=0;for(;n0&&(t=this.toString("hex",0,50).match(/.{2}/g).join(" "),this.length>50&&(t+=" ... ")),""},ge.prototype.compare=function(t,r,e,n,o){if(!we(t))throw new TypeError("Argument must be a Buffer");if(void 0===r&&(r=0),void 0===e&&(e=t?t.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),r<0||e>t.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&r>=e)return 0;if(n>=o)return-1;if(r>=e)return 1;if(this===t)return 0;for(var i=(o>>>=0)-(n>>>=0),u=(e>>>=0)-(r>>>=0),a=Math.min(i,u),f=this.slice(n,o),s=t.slice(r,e),c=0;co)&&(e=o),t.length>0&&(e<0||r<0)||r>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return Pe(this,t,r,e);case"utf8":case"utf-8":return Re(this,t,r,e);case"ascii":return Oe(this,t,r,e);case"latin1":case"binary":return Te(this,t,r,e);case"base64":return Se(this,t,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Ue(this,t,r,e);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},ge.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Ie(t,r,e){var n="";e=Math.min(t.length,e);for(var o=r;on)&&(e=n);for(var o="",i=r;ie)throw new RangeError("Trying to access beyond buffer length")}function De(t,r,e,n,o,i){if(!we(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(r>o||rt.length)throw new RangeError("Index out of range")}function Le(t,r,e,n){r<0&&(r=65535+r+1);for(var o=0,i=Math.min(t.length-e,2);o>>8*(n?o:1-o)}function ze(t,r,e,n){r<0&&(r=4294967295+r+1);for(var o=0,i=Math.min(t.length-e,4);o>>8*(n?o:3-o)&255}function Fe(t,r,e,n,o,i){if(e+n>t.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function qe(t,r,e,n,o){return o||Fe(t,0,e,4),se(t,r,e,n,23,4),e+4}function Je(t,r,e,n,o){return o||Fe(t,0,e,8),se(t,r,e,n,52,8),e+8}ge.prototype.slice=function(t,r){var e,n=this.length;if((t=~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),(r=void 0===r?n:~~r)<0?(r+=n)<0&&(r=0):r>n&&(r=n),r0&&(o*=256);)n+=this[t+--r]*o;return n},ge.prototype.readUInt8=function(t,r){return r||ke(t,1,this.length),this[t]},ge.prototype.readUInt16LE=function(t,r){return r||ke(t,2,this.length),this[t]|this[t+1]<<8},ge.prototype.readUInt16BE=function(t,r){return r||ke(t,2,this.length),this[t]<<8|this[t+1]},ge.prototype.readUInt32LE=function(t,r){return r||ke(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},ge.prototype.readUInt32BE=function(t,r){return r||ke(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},ge.prototype.readIntLE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=this[t],o=1,i=0;++i=(o*=128)&&(n-=Math.pow(2,8*r)),n},ge.prototype.readIntBE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=r,o=1,i=this[t+--n];n>0&&(o*=256);)i+=this[t+--n]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*r)),i},ge.prototype.readInt8=function(t,r){return r||ke(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},ge.prototype.readInt16LE=function(t,r){r||ke(t,2,this.length);var e=this[t]|this[t+1]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt16BE=function(t,r){r||ke(t,2,this.length);var e=this[t+1]|this[t]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt32LE=function(t,r){return r||ke(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},ge.prototype.readInt32BE=function(t,r){return r||ke(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},ge.prototype.readFloatLE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!0,23,4)},ge.prototype.readFloatBE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!1,23,4)},ge.prototype.readDoubleLE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!0,52,8)},ge.prototype.readDoubleBE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!1,52,8)},ge.prototype.writeUIntLE=function(t,r,e,n){(t=+t,r|=0,e|=0,n)||De(this,t,r,e,Math.pow(2,8*e)-1,0);var o=1,i=0;for(this[r]=255&t;++i=0&&(i*=256);)this[r+o]=t/i&255;return r+e},ge.prototype.writeUInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,255,0),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[r]=255&t,r+1},ge.prototype.writeUInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeUInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeUInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r+3]=t>>>24,this[r+2]=t>>>16,this[r+1]=t>>>8,this[r]=255&t):ze(this,t,r,!0),r+4},ge.prototype.writeUInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeIntLE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=0,u=1,a=0;for(this[r]=255&t;++i>0)-a&255;return r+e},ge.prototype.writeIntBE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=e-1,u=1,a=0;for(this[r+i]=255&t;--i>=0&&(u*=256);)t<0&&0===a&&0!==this[r+i+1]&&(a=1),this[r+i]=(t/u>>0)-a&255;return r+e},ge.prototype.writeInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,127,-128),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[r]=255&t,r+1},ge.prototype.writeInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8,this[r+2]=t>>>16,this[r+3]=t>>>24):ze(this,t,r,!0),r+4},ge.prototype.writeInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeFloatLE=function(t,r,e){return qe(this,t,r,!0,e)},ge.prototype.writeFloatBE=function(t,r,e){return qe(this,t,r,!1,e)},ge.prototype.writeDoubleLE=function(t,r,e){return Je(this,t,r,!0,e)},ge.prototype.writeDoubleBE=function(t,r,e){return Je(this,t,r,!1,e)},ge.prototype.copy=function(t,r,e,n){if(e||(e=0),n||0===n||(n=this.length),r>=t.length&&(r=t.length),r||(r=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-r=0;--o)t[o+r]=this[o+e];else if(i<1e3||!ge.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,e=void 0===e?this.length:e>>>0,t||(t=0),"number"==typeof t)for(i=r;i55295&&e<57344){if(!o){if(e>56319){(r-=3)>-1&&i.push(239,191,189);continue}if(u+1===n){(r-=3)>-1&&i.push(239,191,189);continue}o=e;continue}if(e<56320){(r-=3)>-1&&i.push(239,191,189),o=e;continue}e=65536+(o-55296<<10|e-56320)}else o&&(r-=3)>-1&&i.push(239,191,189);if(o=null,e<128){if((r-=1)<0)break;i.push(e)}else if(e<2048){if((r-=2)<0)break;i.push(e>>6|192,63&e|128)}else if(e<65536){if((r-=3)<0)break;i.push(e>>12|224,e>>6&63|128,63&e|128)}else{if(!(e<1114112))throw new Error("Invalid code point");if((r-=4)<0)break;i.push(e>>18|240,e>>12&63|128,e>>6&63|128,63&e|128)}}return i}function Ve(t){return function(t){var r,e,n,o,i,u;oe||ie();var a=t.length;if(a%4>0)throw new Error("Invalid string. Length must be a multiple of 4");i="="===t[a-2]?2:"="===t[a-1]?1:0,u=new ne(3*a/4-i),n=i>0?a-4:a;var f=0;for(r=0,e=0;r>16&255,u[f++]=o>>8&255,u[f++]=255&o;return 2===i?(o=ee[t.charCodeAt(r)]<<2|ee[t.charCodeAt(r+1)]>>4,u[f++]=255&o):1===i&&(o=ee[t.charCodeAt(r)]<<10|ee[t.charCodeAt(r+1)]<<4|ee[t.charCodeAt(r+2)]>>2,u[f++]=o>>8&255,u[f++]=255&o),u}(function(t){if((t=function(t){if(t.trim)return t.trim();return t.replace(/^\s+|\s+$/g,"")}(t).replace($e,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function He(t,r,e,n){for(var o=0;o=r.length||o>=t.length);++o)r[o+e]=t[o];return o}function We(t){return null!=t&&(!!t._isBuffer||Ze(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&Ze(t.slice(0,0))}(t))}function Ze(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}var Ke=function(t,r){if(r instanceof Error){var e={};return Object.getOwnPropertyNames(r).forEach((function(t){e[t]=r[t]})),e}return r};var Xe=function(t,r){try{var e=t.headers.accept.split(",");return r?e.filter((function(t){return t===r})):e}catch(t){return[]}},tn=function(t,r){return!!Xe(t,r).length},rn=function(t,r){return t.path===r.jsonqlPath};exports.VERSION="1.2.3",exports.assign=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return console.info("assing",t),Reflect.apply(Object.assign,Object,t)},exports.buff=function(t,r){return void 0===r&&(r="base64"),We(t)?t:new ge.from(t,r)},exports.cacheBurst=Yr,exports.cacheBurstUrl=function(t){return Cr(t,Yr())},exports.chainFns=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},exports.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):xr(t,e)}))}))}),Promise.resolve(!1===r?[]:j(r)?r:{}))},exports.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("acknowledge_reply",t,r,e)},exports.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},exports.createMutation=Jr,exports.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Jr(t,r,e,n))},exports.createQuery=qr,exports.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},exports.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("emit_reply",t,r,e)},exports.createWsReply=Xr,exports.dasherize=Ir,exports.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ur("Unknown "+r+" to extract argument from!")}},exports.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Tr(e,r);return n}catch(t){throw new Tr(e,t)}},exports.extractSocketPart=Br,exports.extractWsPayload=function(t,r){void 0===r&&(r=Z);try{var e,n=W(t);if(!1!==(e=te(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ur("payload can not decoded",t)}catch(t){return r("error",t)}},exports.findFromContract=function(t,e,n){return!!(n[t]&&n[t][e]&&n[t][e].file&&r.existsSync(n[t][e].file))&&n[t][e].file},exports.formatPayload=Lr,exports.getCallMethod=function(t){switch(!0){case t===Rr[0]:return"query";case t===Rr[1]:return"mutation";default:return!1}},exports.getConfigValue=function(t,r){return r&&j(r)&&t in r?r[t]:void 0},exports.getDocLen=function(t){return ge.byteLength(t,"utf8")},exports.getMutationFromArgs=Qr,exports.getMutationFromPayload=function(t){var r=Gr(t,Qr);if(!1!==r)return r;throw new Sr("[getMutationArgs] Payload is malformed!",t)},exports.getNamespace=Wr,exports.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},exports.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Wr(t),o=e?Hr(r):function(t,r){var e,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},exports.getPathToFn=function(t,n,o){var i=o.resolverDir,u=Ir(t),a=[];o.contract&&o.contract[n]&&o.contract[n].path&&a.push(o.contract[n].path),a.push(e.join(i,n,u,[Or,Pr].join("."))),a.push(e.join(i,n,[u,Pr].join(".")));for(var f=a.length,s=0;s=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var i=Array(o);++n-1;);return e}(o,i),function(t,r){for(var e=t.length;e--&&U(r,t[e],0)>-1;);return e}(o,i)+1).join("")}var G=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return n(t)?t:[t]},V=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},H=function(t,r){try{var e=Object.keys(t);return G(e,r)}catch(t){return!1}},W=function(t){return V("string"==typeof t?t:JSON.stringify(t))},Z=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function X(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var tt=Array.prototype.splice;function rt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},rt.prototype.set=function(t,r){var e=this.__data__,n=X(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function nt(t){if(!et(t))return!1;var r=y(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var ot,it=a["__core-js_shared__"],ut=(ot=/[^.]+$/.exec(it&&it.keys&&it.keys.IE_PROTO||""))?"Symbol(src)_1."+ot:"";var at=Function.prototype.toString;var ft=/^\[object .+?Constructor\]$/,st=Function.prototype,ct=Object.prototype,ht=st.toString,pt=ct.hasOwnProperty,lt=RegExp("^"+ht.call(pt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function gt(t){return!(!et(t)||function(t){return!!ut&&ut in t}(t))&&(nt(t)?lt:ft).test(function(t){if(null!=t){try{return at.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function yt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return gt(e)?e:void 0}var vt=yt(a,"Map"),dt=yt(Object,"create");var _t=Object.prototype.hasOwnProperty;var bt=Object.prototype.hasOwnProperty;function wt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Jt(t.length)&&!nt(t)}var Gt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Qt=Gt&&"object"==typeof module&&module&&!module.nodeType&&module,Vt=Qt&&Qt.exports===Gt?a.Buffer:void 0,Ht=(Vt?Vt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Zt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Kt=Zt&&"object"==typeof module&&module&&!module.nodeType&&module,Xt=Kt&&Kt.exports===Zt&&i.process,tr=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Xt&&Xt.binding&&Xt.binding("util")}catch(t){}}(),rr=tr&&tr.isTypedArray,er=rr?function(t){return function(r){return t(r)}}(rr):function(t){return b(t)&&Jt(t.length)&&!!Wt[y(t)]};function nr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var or=Object.prototype.hasOwnProperty;function ir(t,r,e){var n=t[r];or.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||jt(t,r,e)}var ur=/^(?:0|[1-9]\d*)$/;function ar(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&ur.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(br);function Ar(t,r){return mr(function(t,r,e){return r=_r(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,i=_r(n.length-r,0),u=Array(i);++o1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=Er.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!et(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ar(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e>18&63]+re[o>>12&63]+re[o>>6&63]+re[63&o]);return i.join("")}function ae(t){var r;oe||ie();for(var e=t.length,n=e%3,o="",i=[],u=0,a=e-n;ua?a:u+16383));return 1===n?(r=t[e-1],o+=re[r>>2],o+=re[r<<4&63],o+="=="):2===n&&(r=(t[e-2]<<8)+t[e-1],o+=re[r>>10],o+=re[r>>4&63],o+=re[r<<2&63],o+="="),i.push(o),i.join("")}function fe(t,r,e,n,o){var i,u,a=8*o-n-1,f=(1<>1,c=-7,h=e?o-1:0,p=e?-1:1,l=t[r+h];for(h+=p,i=l&(1<<-c)-1,l>>=-c,c+=a;c>0;i=256*i+t[r+h],h+=p,c-=8);for(u=i&(1<<-c)-1,i>>=-c,c+=n;c>0;u=256*u+t[r+h],h+=p,c-=8);if(0===i)i=1-s;else{if(i===f)return u?NaN:1/0*(l?-1:1);u+=Math.pow(2,n),i-=s}return(l?-1:1)*u*Math.pow(2,i-n)}function se(t,r,e,n,o,i){var u,a,f,s=8*i-o-1,c=(1<>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,l=n?0:i-1,g=n?1:-1,y=r<0||0===r&&1/r<0?1:0;for(r=Math.abs(r),isNaN(r)||r===1/0?(a=isNaN(r)?1:0,u=c):(u=Math.floor(Math.log(r)/Math.LN2),r*(f=Math.pow(2,-u))<1&&(u--,f*=2),(r+=u+h>=1?p/f:p*Math.pow(2,1-h))*f>=2&&(u++,f/=2),u+h>=c?(a=0,u=c):u+h>=1?(a=(r*f-1)*Math.pow(2,o),u+=h):(a=r*Math.pow(2,h-1)*Math.pow(2,o),u=0));o>=8;t[e+l]=255&a,l+=g,a/=256,o-=8);for(u=u<0;t[e+l]=255&u,l+=g,u/=256,s-=8);t[e+l-g]|=128*y}var ce={}.toString,he=Array.isArray||function(t){return"[object Array]"==ce.call(t)};function pe(){return ge.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function le(t,r){if(pe()=pe())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+pe().toString(16)+" bytes");return 0|t}function we(t){return!(null==t||!t._isBuffer)}function me(t,r){if(we(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var e=t.length;if(0===e)return 0;for(var n=!1;;)switch(r){case"ascii":case"latin1":case"binary":return e;case"utf8":case"utf-8":case void 0:return Qe(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*e;case"hex":return e>>>1;case"base64":return Ve(t).length;default:if(n)return Qe(t).length;r=(""+r).toLowerCase(),n=!0}}function Ae(t,r,e){var n=!1;if((void 0===r||r<0)&&(r=0),r>this.length)return"";if((void 0===e||e>this.length)&&(e=this.length),e<=0)return"";if((e>>>=0)<=(r>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return Ye(this,r,e);case"utf8":case"utf-8":return Ne(this,r,e);case"ascii":return Ie(this,r,e);case"latin1":case"binary":return Ce(this,r,e);case"base64":return Be(this,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Me(this,r,e);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function Ee(t,r,e){var n=t[r];t[r]=t[e],t[e]=n}function xe(t,r,e,n,o){if(0===t.length)return-1;if("string"==typeof e?(n=e,e=0):e>2147483647?e=2147483647:e<-2147483648&&(e=-2147483648),e=+e,isNaN(e)&&(e=o?0:t.length-1),e<0&&(e=t.length+e),e>=t.length){if(o)return-1;e=t.length-1}else if(e<0){if(!o)return-1;e=0}if("string"==typeof r&&(r=ge.from(r,n)),we(r))return 0===r.length?-1:je(t,r,e,n,o);if("number"==typeof r)return r&=255,ge.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,r,e):Uint8Array.prototype.lastIndexOf.call(t,r,e):je(t,[r],e,n,o);throw new TypeError("val must be string, number or Buffer")}function je(t,r,e,n,o){var i,u=1,a=t.length,f=r.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||r.length<2)return-1;u=2,a/=2,f/=2,e/=2}function s(t,r){return 1===u?t[r]:t.readUInt16BE(r*u)}if(o){var c=-1;for(i=e;ia&&(e=a-f),i=e;i>=0;i--){for(var h=!0,p=0;po&&(n=o):n=o;var i=r.length;if(i%2!=0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var u=0;u>8,o=e%256,i.push(o),i.push(n);return i}(r,t.length-e),t,e,n)}function Be(t,r,e){return 0===r&&e===t.length?ae(t):ae(t.slice(r,e))}function Ne(t,r,e){e=Math.min(t.length,e);for(var n=[],o=r;o239?4:s>223?3:s>191?2:1;if(o+h<=e)switch(h){case 1:s<128&&(c=s);break;case 2:128==(192&(i=t[o+1]))&&(f=(31&s)<<6|63&i)>127&&(c=f);break;case 3:i=t[o+1],u=t[o+2],128==(192&i)&&128==(192&u)&&(f=(15&s)<<12|(63&i)<<6|63&u)>2047&&(f<55296||f>57343)&&(c=f);break;case 4:i=t[o+1],u=t[o+2],a=t[o+3],128==(192&i)&&128==(192&u)&&128==(192&a)&&(f=(15&s)<<18|(63&i)<<12|(63&u)<<6|63&a)>65535&&f<1114112&&(c=f)}null===c?(c=65533,h=1):c>65535&&(c-=65536,n.push(c>>>10&1023|55296),c=56320|1023&c),n.push(c),o+=h}return function(t){var r=t.length;if(r<=4096)return String.fromCharCode.apply(String,t);var e="",n=0;for(;n0&&(t=this.toString("hex",0,50).match(/.{2}/g).join(" "),this.length>50&&(t+=" ... ")),""},ge.prototype.compare=function(t,r,e,n,o){if(!we(t))throw new TypeError("Argument must be a Buffer");if(void 0===r&&(r=0),void 0===e&&(e=t?t.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),r<0||e>t.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&r>=e)return 0;if(n>=o)return-1;if(r>=e)return 1;if(this===t)return 0;for(var i=(o>>>=0)-(n>>>=0),u=(e>>>=0)-(r>>>=0),a=Math.min(i,u),f=this.slice(n,o),s=t.slice(r,e),c=0;co)&&(e=o),t.length>0&&(e<0||r<0)||r>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return Pe(this,t,r,e);case"utf8":case"utf-8":return Re(this,t,r,e);case"ascii":return Oe(this,t,r,e);case"latin1":case"binary":return Te(this,t,r,e);case"base64":return Se(this,t,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Ue(this,t,r,e);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},ge.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Ie(t,r,e){var n="";e=Math.min(t.length,e);for(var o=r;on)&&(e=n);for(var o="",i=r;ie)throw new RangeError("Trying to access beyond buffer length")}function De(t,r,e,n,o,i){if(!we(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(r>o||rt.length)throw new RangeError("Index out of range")}function Le(t,r,e,n){r<0&&(r=65535+r+1);for(var o=0,i=Math.min(t.length-e,2);o>>8*(n?o:1-o)}function ze(t,r,e,n){r<0&&(r=4294967295+r+1);for(var o=0,i=Math.min(t.length-e,4);o>>8*(n?o:3-o)&255}function Fe(t,r,e,n,o,i){if(e+n>t.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function qe(t,r,e,n,o){return o||Fe(t,0,e,4),se(t,r,e,n,23,4),e+4}function Je(t,r,e,n,o){return o||Fe(t,0,e,8),se(t,r,e,n,52,8),e+8}ge.prototype.slice=function(t,r){var e,n=this.length;if((t=~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),(r=void 0===r?n:~~r)<0?(r+=n)<0&&(r=0):r>n&&(r=n),r0&&(o*=256);)n+=this[t+--r]*o;return n},ge.prototype.readUInt8=function(t,r){return r||ke(t,1,this.length),this[t]},ge.prototype.readUInt16LE=function(t,r){return r||ke(t,2,this.length),this[t]|this[t+1]<<8},ge.prototype.readUInt16BE=function(t,r){return r||ke(t,2,this.length),this[t]<<8|this[t+1]},ge.prototype.readUInt32LE=function(t,r){return r||ke(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},ge.prototype.readUInt32BE=function(t,r){return r||ke(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},ge.prototype.readIntLE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=this[t],o=1,i=0;++i=(o*=128)&&(n-=Math.pow(2,8*r)),n},ge.prototype.readIntBE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=r,o=1,i=this[t+--n];n>0&&(o*=256);)i+=this[t+--n]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*r)),i},ge.prototype.readInt8=function(t,r){return r||ke(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},ge.prototype.readInt16LE=function(t,r){r||ke(t,2,this.length);var e=this[t]|this[t+1]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt16BE=function(t,r){r||ke(t,2,this.length);var e=this[t+1]|this[t]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt32LE=function(t,r){return r||ke(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},ge.prototype.readInt32BE=function(t,r){return r||ke(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},ge.prototype.readFloatLE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!0,23,4)},ge.prototype.readFloatBE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!1,23,4)},ge.prototype.readDoubleLE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!0,52,8)},ge.prototype.readDoubleBE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!1,52,8)},ge.prototype.writeUIntLE=function(t,r,e,n){(t=+t,r|=0,e|=0,n)||De(this,t,r,e,Math.pow(2,8*e)-1,0);var o=1,i=0;for(this[r]=255&t;++i=0&&(i*=256);)this[r+o]=t/i&255;return r+e},ge.prototype.writeUInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,255,0),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[r]=255&t,r+1},ge.prototype.writeUInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeUInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeUInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r+3]=t>>>24,this[r+2]=t>>>16,this[r+1]=t>>>8,this[r]=255&t):ze(this,t,r,!0),r+4},ge.prototype.writeUInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeIntLE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=0,u=1,a=0;for(this[r]=255&t;++i>0)-a&255;return r+e},ge.prototype.writeIntBE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=e-1,u=1,a=0;for(this[r+i]=255&t;--i>=0&&(u*=256);)t<0&&0===a&&0!==this[r+i+1]&&(a=1),this[r+i]=(t/u>>0)-a&255;return r+e},ge.prototype.writeInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,127,-128),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[r]=255&t,r+1},ge.prototype.writeInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8,this[r+2]=t>>>16,this[r+3]=t>>>24):ze(this,t,r,!0),r+4},ge.prototype.writeInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeFloatLE=function(t,r,e){return qe(this,t,r,!0,e)},ge.prototype.writeFloatBE=function(t,r,e){return qe(this,t,r,!1,e)},ge.prototype.writeDoubleLE=function(t,r,e){return Je(this,t,r,!0,e)},ge.prototype.writeDoubleBE=function(t,r,e){return Je(this,t,r,!1,e)},ge.prototype.copy=function(t,r,e,n){if(e||(e=0),n||0===n||(n=this.length),r>=t.length&&(r=t.length),r||(r=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-r=0;--o)t[o+r]=this[o+e];else if(i<1e3||!ge.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,e=void 0===e?this.length:e>>>0,t||(t=0),"number"==typeof t)for(i=r;i55295&&e<57344){if(!o){if(e>56319){(r-=3)>-1&&i.push(239,191,189);continue}if(u+1===n){(r-=3)>-1&&i.push(239,191,189);continue}o=e;continue}if(e<56320){(r-=3)>-1&&i.push(239,191,189),o=e;continue}e=65536+(o-55296<<10|e-56320)}else o&&(r-=3)>-1&&i.push(239,191,189);if(o=null,e<128){if((r-=1)<0)break;i.push(e)}else if(e<2048){if((r-=2)<0)break;i.push(e>>6|192,63&e|128)}else if(e<65536){if((r-=3)<0)break;i.push(e>>12|224,e>>6&63|128,63&e|128)}else{if(!(e<1114112))throw new Error("Invalid code point");if((r-=4)<0)break;i.push(e>>18|240,e>>12&63|128,e>>6&63|128,63&e|128)}}return i}function Ve(t){return function(t){var r,e,n,o,i,u;oe||ie();var a=t.length;if(a%4>0)throw new Error("Invalid string. Length must be a multiple of 4");i="="===t[a-2]?2:"="===t[a-1]?1:0,u=new ne(3*a/4-i),n=i>0?a-4:a;var f=0;for(r=0,e=0;r>16&255,u[f++]=o>>8&255,u[f++]=255&o;return 2===i?(o=ee[t.charCodeAt(r)]<<2|ee[t.charCodeAt(r+1)]>>4,u[f++]=255&o):1===i&&(o=ee[t.charCodeAt(r)]<<10|ee[t.charCodeAt(r+1)]<<4|ee[t.charCodeAt(r+2)]>>2,u[f++]=o>>8&255,u[f++]=255&o),u}(function(t){if((t=function(t){if(t.trim)return t.trim();return t.replace(/^\s+|\s+$/g,"")}(t).replace($e,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function He(t,r,e,n){for(var o=0;o=r.length||o>=t.length);++o)r[o+e]=t[o];return o}function We(t){return null!=t&&(!!t._isBuffer||Ze(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&Ze(t.slice(0,0))}(t))}function Ze(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}var Ke=function(t,r){if(r instanceof Error){var e={};return Object.getOwnPropertyNames(r).forEach((function(t){e[t]=r[t]})),e}return r};var Xe=function(t,r){try{var e=t.headers.accept.split(",");return r?e.filter((function(t){return t===r})):e}catch(t){return[]}},tn=function(t,r){return!!Xe(t,r).length},rn=function(t,r){return t.path===r.jsonqlPath};exports.VERSION="1.2.3",exports.assign=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return Reflect.apply(Object.assign,Object,t)},exports.buff=function(t,r){return void 0===r&&(r="base64"),We(t)?t:new ge.from(t,r)},exports.cacheBurst=Yr,exports.cacheBurstUrl=function(t){return Cr(t,Yr())},exports.chainFns=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},exports.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):xr(t,e)}))}))}),Promise.resolve(!1===r?[]:j(r)?r:{}))},exports.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("acknowledge_reply",t,r,e)},exports.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},exports.createMutation=Jr,exports.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Jr(t,r,e,n))},exports.createQuery=qr,exports.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},exports.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("emit_reply",t,r,e)},exports.createWsReply=Xr,exports.dasherize=Ir,exports.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ur("Unknown "+r+" to extract argument from!")}},exports.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Tr(e,r);return n}catch(t){throw new Tr(e,t)}},exports.extractSocketPart=Br,exports.extractWsPayload=function(t,r){void 0===r&&(r=Z);try{var e,n=W(t);if(!1!==(e=te(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ur("payload can not decoded",t)}catch(t){return r("error",t)}},exports.findFromContract=function(t,e,n){return!!(n[t]&&n[t][e]&&n[t][e].file&&r.existsSync(n[t][e].file))&&n[t][e].file},exports.formatPayload=Lr,exports.getCallMethod=function(t){switch(!0){case t===Rr[0]:return"query";case t===Rr[1]:return"mutation";default:return!1}},exports.getConfigValue=function(t,r){return r&&j(r)&&t in r?r[t]:void 0},exports.getDocLen=function(t){return ge.byteLength(t,"utf8")},exports.getMutationFromArgs=Qr,exports.getMutationFromPayload=function(t){var r=Gr(t,Qr);if(!1!==r)return r;throw new Sr("[getMutationArgs] Payload is malformed!",t)},exports.getNamespace=Wr,exports.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},exports.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Wr(t),o=e?Hr(r):function(t,r){var e,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},exports.getPathToFn=function(t,n,o){var i=o.resolverDir,u=Ir(t),a=[];o.contract&&o.contract[n]&&o.contract[n].path&&a.push(o.contract[n].path),a.push(e.join(i,n,u,[Or,Pr].join("."))),a.push(e.join(i,n,[u,Pr].join(".")));for(var f=a.length,s=0;s Date: Tue, 17 Mar 2020 23:11:37 +0800 Subject: [PATCH 36/66] Add a special helloWorld method for testing --- packages/ws-client-core/src/callers/setup-hello.js | 11 +++++++++++ packages/ws-client-core/tests/evt.test.js | 5 +++-- packages/ws-server/client.js | 5 +++-- packages/ws-server/package.json | 4 ++-- packages/ws-server/src/modules.js | 5 ++--- packages/ws-server/tests/init.test.js | 2 +- 6 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 packages/ws-client-core/src/callers/setup-hello.js diff --git a/packages/ws-client-core/src/callers/setup-hello.js b/packages/ws-client-core/src/callers/setup-hello.js new file mode 100644 index 00000000..d68d8b85 --- /dev/null +++ b/packages/ws-client-core/src/callers/setup-hello.js @@ -0,0 +1,11 @@ +// create a stock helloWorld method for tesing the connection +import { HELLO_FN } from 'jsonql-constants' + +/** + * This one is a big special (just like in http) as a built in method to test the connection + * @param {function} deliverFn the framework specific method to send thing + * @return {void} it doesn't return anything because it only responsible send things out + */ +function helloWorld(deliverFn) { + +} diff --git a/packages/ws-client-core/tests/evt.test.js b/packages/ws-client-core/tests/evt.test.js index ef5c632a..16dda639 100644 --- a/packages/ws-client-core/tests/evt.test.js +++ b/packages/ws-client-core/tests/evt.test.js @@ -10,7 +10,8 @@ const logger = debug('jsonql-ws-client:test:evt:logger') const localDebug = debug('jsonql-ws-client:test:evt') const { chainPromises } = require('jsonql-utils') -const { basicClient } = require('jsonql-ws-server/client') + +const { basicClient, fullClient } = require('../../ws-server/client') const wsServer = require('./fixtures/server-setup') const createToken = require('./fixtures/token') @@ -70,6 +71,6 @@ test.cb(`Test the chainPromises to create client`, t => { }) - +test.todo(`Testing the fullClient with csrf`) test.todo(`Testing the switch over callback binding`) diff --git a/packages/ws-server/client.js b/packages/ws-server/client.js index a9bca06d..1cb60996 100644 --- a/packages/ws-server/client.js +++ b/packages/ws-server/client.js @@ -32,9 +32,10 @@ function initConnect(ws) { ws.onmessage = function(payload) { try { + setTimeout(() => { + ws.close() + }, 500) - // ws.close() - resolver(extractPingResult(payload.data)) } catch(e) { rejecter(new JsonqlError('fullClient.onmessage', e)) diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json index 9a472324..34d13f96 100755 --- a/packages/ws-server/package.json +++ b/packages/ws-server/package.json @@ -34,8 +34,8 @@ "colors": "^1.4.0", "debug": "^4.1.1", "jsonql-constants": "^2.0.4", - "jsonql-utils": "^1.2.2", - "jsonql-ws-server-core": "^0.7.8", + "jsonql-utils": "^1.2.3", + "jsonql-ws-server-core": "^0.7.9", "ws": "^7.2.3" }, "devDependencies": { diff --git a/packages/ws-server/src/modules.js b/packages/ws-server/src/modules.js index 482e95a9..9ffd3acb 100644 --- a/packages/ws-server/src/modules.js +++ b/packages/ws-server/src/modules.js @@ -19,10 +19,9 @@ const { SOCKET_STATE_KEY, getSocketHandler -} = require('../../ws-server-core') -// require('jsonql-ws-server-core') +} = require('jsonql-ws-server-core') +// require('../../ws-server-core') - module.exports = { WebSocket, // ours diff --git a/packages/ws-server/tests/init.test.js b/packages/ws-server/tests/init.test.js index 328d4ad6..a1217ab7 100644 --- a/packages/ws-server/tests/init.test.js +++ b/packages/ws-server/tests/init.test.js @@ -21,7 +21,7 @@ const contract = fsx.readJsonSync(contractFile) const { extractWsPayload } = require('jsonql-ws-server-core') const createPayload = require('./fixtures/create-payload') const port = 8899 -const msg = 'Something' +// const msg = 'Something' // let ctn = 0; test.before(async t => { -- Gitee From 893edeb44f3689782500db5045c56cd75cb158e5 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 17 Mar 2020 23:14:41 +0800 Subject: [PATCH 37/66] move the intercome-methods out into the caller --- packages/ws-client-core/src/callers/index.js | 14 +++++++++++++- .../src/{listener => callers}/intercom-methods.js | 0 2 files changed, 13 insertions(+), 1 deletion(-) rename packages/ws-client-core/src/{listener => callers}/intercom-methods.js (100%) diff --git a/packages/ws-client-core/src/callers/index.js b/packages/ws-client-core/src/callers/index.js index f2b12064..b93d9d72 100644 --- a/packages/ws-client-core/src/callers/index.js +++ b/packages/ws-client-core/src/callers/index.js @@ -1,5 +1,17 @@ // just doing the import export thing here +// we move the following methods from listener to callers +// because they are actually sending things out not react to anything +import { + createInitPing, + extractPingResult, + createIntercomPayload +} from './intercom-methods' import { callersGenerator } from './callers-generator' // just rename it -export { callersGenerator } +export { + createInitPing, + extractPingResult, + createIntercomPayload, + callersGenerator +} diff --git a/packages/ws-client-core/src/listener/intercom-methods.js b/packages/ws-client-core/src/callers/intercom-methods.js similarity index 100% rename from packages/ws-client-core/src/listener/intercom-methods.js rename to packages/ws-client-core/src/callers/intercom-methods.js -- Gitee From dc1ff0ba1d1d013c7c12b0eddf4338a568796d12 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 00:02:54 +0800 Subject: [PATCH 38/66] group all the import export --- packages/ws-client-core/index.js | 42 ++++++++----------- .../src/callers/{setup-hello.js => hello.js} | 6 +-- packages/ws-client-core/src/callers/index.js | 4 ++ packages/ws-client-core/src/listener/index.js | 23 ++++++++++ packages/ws-client-core/src/utils/index.js | 5 ++- 5 files changed, 51 insertions(+), 29 deletions(-) rename packages/ws-client-core/src/callers/{setup-hello.js => hello.js} (73%) create mode 100644 packages/ws-client-core/src/listener/index.js diff --git a/packages/ws-client-core/index.js b/packages/ws-client-core/index.js index c43ffd49..06537534 100644 --- a/packages/ws-client-core/index.js +++ b/packages/ws-client-core/index.js @@ -10,39 +10,32 @@ import { } from './src/options' // these were in the share.js and now we combine into one import * as jsonqlWsConstants from './src/options/constants' -// moving it back because it's the same for two different framework + import { createNspClient, - createNspAuthClient -} from './src/listener/create-nsp-clients' -// error handler -import { + createNspAuthClient, + clientEventListener, triggerNamespacesOnError, handleNamespaceOnError -} from './src/listener/trigger-namespaces-on-error' +} from './src/listener' + import { + EventEmitterClass, getEventEmitter, - EventEmitterClass -} from './src/utils/get-event-emitter' -// also export some of the util methods -import { - fixWss, - clearMainEmitEvt -} from './src/utils/helpers' -// this one bind the framework engine and our event engine together -import { - clientEventListener -} from './src/listener/client-event-listener' -// The onion skin cooker -import { - createCombineClient -} from './src/create-combine-client' + clearMainEmitEvt, + fixWss +} from './src/utils' // new ping methods import { createInitPing, extractPingResult, - createIntercomPayload -} from './src/listener/intercom-methods' + createIntercomPayload, + helloWorld +} from './src/callers' +// The onion skin cooker +import { + createCombineClient +} from './src/create-combine-client' // export export { @@ -73,5 +66,6 @@ export { createInitPing, extractPingResult, - createIntercomPayload + createIntercomPayload, + helloWorld } diff --git a/packages/ws-client-core/src/callers/setup-hello.js b/packages/ws-client-core/src/callers/hello.js similarity index 73% rename from packages/ws-client-core/src/callers/setup-hello.js rename to packages/ws-client-core/src/callers/hello.js index d68d8b85..b7e90ce4 100644 --- a/packages/ws-client-core/src/callers/setup-hello.js +++ b/packages/ws-client-core/src/callers/hello.js @@ -1,11 +1,11 @@ // create a stock helloWorld method for tesing the connection import { HELLO_FN } from 'jsonql-constants' - +import { createQueryStr } from 'jsonql-utils/module' /** * This one is a big special (just like in http) as a built in method to test the connection * @param {function} deliverFn the framework specific method to send thing * @return {void} it doesn't return anything because it only responsible send things out */ -function helloWorld(deliverFn) { - +export function helloWorld(deliverFn) { + deliverFn(createQueryStr(HELLO_FN, [])) } diff --git a/packages/ws-client-core/src/callers/index.js b/packages/ws-client-core/src/callers/index.js index b93d9d72..6675b923 100644 --- a/packages/ws-client-core/src/callers/index.js +++ b/packages/ws-client-core/src/callers/index.js @@ -1,6 +1,9 @@ // just doing the import export thing here // we move the following methods from listener to callers // because they are actually sending things out not react to anything +import { + helloWorld +} from './hello' import { createInitPing, extractPingResult, @@ -10,6 +13,7 @@ import { import { callersGenerator } from './callers-generator' // just rename it export { + helloWorld, createInitPing, extractPingResult, createIntercomPayload, diff --git a/packages/ws-client-core/src/listener/index.js b/packages/ws-client-core/src/listener/index.js new file mode 100644 index 00000000..4d384771 --- /dev/null +++ b/packages/ws-client-core/src/listener/index.js @@ -0,0 +1,23 @@ +// moving it back because it's the same for two different framework +import { + createNspClient, + createNspAuthClient +} from './create-nsp-clients' +// this one bind the framework engine and our event engine together +import { + clientEventListener +} from './client-event-listener' +// error handler +import { + triggerNamespacesOnError, + handleNamespaceOnError +} from './trigger-namespaces-on-error' + +// group all the import export in one place +export { + createNspClient, + createNspAuthClient, + clientEventListener, + triggerNamespacesOnError, + handleNamespaceOnError +} \ No newline at end of file diff --git a/packages/ws-client-core/src/utils/index.js b/packages/ws-client-core/src/utils/index.js index 6aa032a4..e782324d 100644 --- a/packages/ws-client-core/src/utils/index.js +++ b/packages/ws-client-core/src/utils/index.js @@ -1,7 +1,7 @@ // export the util methods import { isArray, isString } from 'jsonql-params-validator' import { getLogFn } from './get-log-fn' -import { getEventEmitter } from './get-event-emitter' +import { getEventEmitter, EventEmitterClass } from './get-event-emitter' // moved to jsonql-utils // some of these are unnecessary export should get rip of them import { @@ -29,7 +29,8 @@ import { export { getLogFn, getEventEmitter, - + EventEmitterClass, + isArray, isString, -- Gitee From e8ee99266f4897d4b167c6e0ef6a4ebb7f863691 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 08:29:28 +0800 Subject: [PATCH 39/66] just experiement some object define prop but not going to implement it --- packages/utils/src/generic.js | 2 +- packages/utils/tests/define-property.test.js | 51 ++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/packages/utils/src/generic.js b/packages/utils/src/generic.js index d50572ee..2cde7589 100644 --- a/packages/utils/src/generic.js +++ b/packages/utils/src/generic.js @@ -103,7 +103,7 @@ export const isFunc = prop => { * @return {object} merge together object by key */ export const assign = (...args) => Reflect.apply(Object.assign, Object, args) - + // generic placeholder function export const nil = () => false diff --git a/packages/utils/tests/define-property.test.js b/packages/utils/tests/define-property.test.js index 898a06ae..086656d7 100644 --- a/packages/utils/tests/define-property.test.js +++ b/packages/utils/tests/define-property.test.js @@ -41,3 +41,54 @@ test(`It should able to check the property using objHasProp`, t => { t.is(result2, value) }) + + +test(`Testing a new concept about setting a property for internal use`, t => { + + function someFunction(...args) { + // console.log(someFunction.max) + if (someFunction.max > -1) { + let values = args.filter((arg, i) => i < someFunction.max) + return values.length + } + return args.length + } + + someFunction = injectToFn(someFunction, 'container', -1, true) + + someFunction = objDefineProps(someFunction, 'max', function setter(value) { + someFunction.container = value + // console.log(someFunction.container, value) + }, function getter() { + return someFunction.container + }) + + t.is(someFunction.max, -1, 'Check if the default value is set') + + someFunction.max = 2 + const result = someFunction(1,2,3,4,5) + + t.is(result, 2, 'Test if the max value change the return result') + +}) + + +test.skip(`Test another concept about chaining function`, t => { + + function chainFunction(...args) { + return args.length + } + + chainFunction = injectToFn(someFunction, 'value', -1, true) + + chainFunction = objDefineProps(chainFunction, 'max', function(value) { + chainFunction.value = value + }, function getter() { + return function applyValue(value) { + chainFunction.value = value + } + }) + + chainFunction.max(2) + +}) \ No newline at end of file -- Gitee From 3665b8b9b4f64eebbc179b1351af6da3a90c25bf Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 09:03:29 +0800 Subject: [PATCH 40/66] update the content from helloWorld return message --- packages/ws-client-core/tests/evt.test.js | 29 ++++++++++++++++++- packages/ws-server-core/package.json | 2 +- .../src/handles/get-socket-handler.js | 2 +- .../src/handles/handle-hello.js | 8 +++-- packages/ws-server/client.js | 8 +++-- 5 files changed, 41 insertions(+), 8 deletions(-) diff --git a/packages/ws-client-core/tests/evt.test.js b/packages/ws-client-core/tests/evt.test.js index 16dda639..a6ae8c81 100644 --- a/packages/ws-client-core/tests/evt.test.js +++ b/packages/ws-client-core/tests/evt.test.js @@ -71,6 +71,33 @@ test.cb(`Test the chainPromises to create client`, t => { }) -test.todo(`Testing the fullClient with csrf`) +test.cb.only(`Testing the fullClient with csrf`, t => { + t.plan(2) + + chainPromises([ + fullClient([baseUrl, namespaces[1]].join('/'), t.context.token), + fullClient([baseUrl, namespaces[0]].join('/')) + ]).then(clients => clients + .map((client, i) => { + return {[namespaces[i]]: client} + }) + .reduce((a, b) => Object.assign(a, b), {}) + ) + .then(clients => { + const c1 = clients.public + const c2 = clients.private + + c1.onopen = function() { + t.pass() + } + + c2.onopen = function() { + t.pass() + t.end() + } + + }) + +}) test.todo(`Testing the switch over callback binding`) diff --git a/packages/ws-server-core/package.json b/packages/ws-server-core/package.json index 97be56eb..8b43f936 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.7.9", + "version": "0.7.10", "description": "This is the core module that drive the Jsonql WS Socket server, not for direct use.", "main": "index.js", "files": [ diff --git a/packages/ws-server-core/src/handles/get-socket-handler.js b/packages/ws-server-core/src/handles/get-socket-handler.js index 4691a70a..96d0445b 100644 --- a/packages/ws-server-core/src/handles/get-socket-handler.js +++ b/packages/ws-server-core/src/handles/get-socket-handler.js @@ -55,7 +55,7 @@ function getSocketHandler(config, ws, deliverFn, req, connectedNamespace, payloa // We don't need to send anything back // @TBC do we need the config return handleInterCom(config, ws, deliverFn, req, connectedNamespace, args, userdata) case resolverName === HELLO_FN: - return handleHello(deliverFn) + return handleHello(deliverFn, connectedNamespace, userdata) default: const contractParam = matchResolverByNamespace(resolverName, connectedNamespace, nspGroup) if (contractParam === false) { diff --git a/packages/ws-server-core/src/handles/handle-hello.js b/packages/ws-server-core/src/handles/handle-hello.js index 8e905ed1..5e60d066 100644 --- a/packages/ws-server-core/src/handles/handle-hello.js +++ b/packages/ws-server-core/src/handles/handle-hello.js @@ -2,9 +2,13 @@ const { deliverMsg } = require('../share/resolver-methods') const { HELLO_FN, HELLO } = require('jsonql-constants') -function handleHello(deliverFn) { +function handleHello(deliverFn, connectedNamespace, userdata) { - deliverMsg(deliverFn, HELLO_FN, HELLO) + // change the return message + const world = userdata && userdata.name ? HELLO.replace('world', userdata.name) : HELLO + const msg = `From: ${connectedNamespace}, ${world}` + + deliverMsg(deliverFn, HELLO_FN, msg) } module.exports = { handleHello } \ No newline at end of file diff --git a/packages/ws-server/client.js b/packages/ws-server/client.js index 1cb60996..0e21505c 100644 --- a/packages/ws-server/client.js +++ b/packages/ws-server/client.js @@ -32,10 +32,12 @@ function initConnect(ws) { ws.onmessage = function(payload) { try { + /* setTimeout(() => { - ws.close() - }, 500) - + ws.terminate() + }, 300) + */ + ws.terminate() resolver(extractPingResult(payload.data)) } catch(e) { rejecter(new JsonqlError('fullClient.onmessage', e)) -- Gitee From f11c952a9c1946a9266a975be5c8751d052d626e Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 09:13:21 +0800 Subject: [PATCH 41/66] change the test name to experiement to be more appropriate --- packages/ws-client-core/package.json | 2 +- .../tests/{evt.test.js => experiment.test.js} | 0 packages/ws-server/src/modules.js | 6 +++--- 3 files changed, 4 insertions(+), 4 deletions(-) rename packages/ws-client-core/tests/{evt.test.js => experiment.test.js} (100%) diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json index 7fd9ad0f..c3e69092 100644 --- a/packages/ws-client-core/package.json +++ b/packages/ws-client-core/package.json @@ -14,7 +14,7 @@ "prepare": "npm run test", "update:version": "node ./build.js", "test:tbd": "DEBUG=jsonql-ws* ava ./tests/tbd.test.js", - "test:evt": "DEBUG=jsonql-ws* ava ./tests/evt.test.js", + "test:exp": "DEBUG=jsonql-ws* ava ./tests/experiment.test.js", "test:event": "DEBUG=jsonql-ws* ava ./tests/event.test.js", "test:init": "DEBUG=jsonql-ws* ava ./tests/init.test.js", "test:auth": "DEBUG=jsonql-ws* ava ./tests/auth.test.js", diff --git a/packages/ws-client-core/tests/evt.test.js b/packages/ws-client-core/tests/experiment.test.js similarity index 100% rename from packages/ws-client-core/tests/evt.test.js rename to packages/ws-client-core/tests/experiment.test.js diff --git a/packages/ws-server/src/modules.js b/packages/ws-server/src/modules.js index 9ffd3acb..193e7837 100644 --- a/packages/ws-server/src/modules.js +++ b/packages/ws-server/src/modules.js @@ -19,9 +19,9 @@ const { SOCKET_STATE_KEY, getSocketHandler -} = require('jsonql-ws-server-core') -// require('../../ws-server-core') - +} = require('../../ws-server-core') +// require('jsonql-ws-server-core') + module.exports = { WebSocket, // ours -- Gitee From 69e00aa3ed6894f6b7ef7b1f5f5192b9e6c4616b Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 11:30:24 +0800 Subject: [PATCH 42/66] jsonql-utils to 1.2.4 --- packages/utils/README.md | 11 +++-- packages/utils/browser.js | 2 +- packages/utils/index.js | 2 + packages/utils/main.js | 2 +- packages/utils/module.js | 4 +- packages/utils/package.json | 6 +-- packages/utils/src/generic.js | 11 ++++- packages/utils/tests/construct.test.js | 23 ++++++++++- packages/ws-client-core/index.js | 2 + packages/ws-client-core/src/callers/hello.js | 10 +++++ packages/ws-client-core/src/callers/index.js | 4 +- .../src/callers/intercom-methods.js | 19 +++++++-- .../ws-client-core/tests/experiment.test.js | 40 ++++++++++++++++++- 13 files changed, 115 insertions(+), 21 deletions(-) diff --git a/packages/utils/README.md b/packages/utils/README.md index 4a891192..e54b7ba0 100644 --- a/packages/utils/README.md +++ b/packages/utils/README.md @@ -55,6 +55,9 @@ Please reference which functions in what file below - toJson - isNotEmpty - isFunc +- nil (placeholder function always return false) +- assign (alias to Object.assign) +- freeze (alias to Object.freeze) #### src/logger.js @@ -82,10 +85,6 @@ Please reference which functions in what file below - getMutationFromArgs - getMutationFromPayload -#### src/pre-config-check.js - -- preConfigCheck - #### src/results.js - getCallMethod @@ -139,7 +138,7 @@ import { chainFns } from 'jsonql-utils/module' But this doesn't help with the tree shaking (Tree shaking is a total lie anyway). So you might want to import like what it show in the above section. -For cjs then just do it like you normally would. +For node/cjs then just do it like you normally would. ```js @@ -151,4 +150,4 @@ const { chainFns } = require('jsonql-utils') ISC -Joel Chu (c) 2019 +Joel Chu (c) 2020 diff --git a/packages/utils/browser.js b/packages/utils/browser.js index 41c691d7..92216041 100644 --- a/packages/utils/browser.js +++ b/packages/utils/browser.js @@ -1,2 +1,2 @@ -!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t=t||self).jsonqlUtils={})}(this,(function(t){"use strict";var r=Array.isArray,e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},n="object"==typeof e&&e&&e.Object===Object&&e,o="object"==typeof self&&self&&self.Object===Object&&self,u=n||o||Function("return this")(),i=u.Symbol,a=Object.prototype,c=a.hasOwnProperty,f=a.toString,s=i?i.toStringTag:void 0;var l=Object.prototype.toString;var p=i?i.toStringTag:void 0;function v(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":p&&p in Object(t)?function(t){var r=c.call(t,s),e=t[s];try{t[s]=void 0;var n=!0}catch(t){}var o=f.call(t);return n&&(r?t[s]=e:delete t[s]),o}(t):function(t){return l.call(t)}(t)}var d,y,h=(d=Object.getPrototypeOf,y=Object,function(t){return d(y(t))});function g(t){return null!=t&&"object"==typeof t}var _=Function.prototype,b=Object.prototype,j=_.toString,m=b.hasOwnProperty,O=j.call(Object);function w(t){if(!g(t)||"[object Object]"!=v(t))return!1;var r=h(t);if(null===r)return!0;var e=m.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&j.call(e)==O}var S=i?i.prototype:void 0,P=S?S.toString:void 0;function N(t){if("string"==typeof t)return t;if(r(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var u=Array(o);++n-1;);return e}(o,u),function(t,r){for(var e=t.length;e--&&E(r,t[e],0)>-1;);return e}(o,u)+1).join("")}var I=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return r(t)?t:[t]},L=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},V=function(t,r){try{var e=Object.keys(t);return I(e,r)}catch(t){return!1}},W=function(t){return L("string"==typeof t?t:JSON.stringify(t))},H=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function Z(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var X=Array.prototype.splice;function Y(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},Y.prototype.set=function(t,r){var e=this.__data__,n=Z(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function rt(t){if(!tt(t))return!1;var r=v(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var et,nt=u["__core-js_shared__"],ot=(et=/[^.]+$/.exec(nt&&nt.keys&&nt.keys.IE_PROTO||""))?"Symbol(src)_1."+et:"";var ut=Function.prototype.toString;var it=/^\[object .+?Constructor\]$/,at=Function.prototype,ct=Object.prototype,ft=at.toString,st=ct.hasOwnProperty,lt=RegExp("^"+ft.call(st).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pt(t){return!(!tt(t)||function(t){return!!ot&&ot in t}(t))&&(rt(t)?lt:it).test(function(t){if(null!=t){try{return ut.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function vt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pt(e)?e:void 0}var dt=vt(u,"Map"),yt=vt(Object,"create");var ht=Object.prototype.hasOwnProperty;var gt=Object.prototype.hasOwnProperty;function _t(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Gt(t.length)&&!rt(t)}var It="object"==typeof t&&t&&!t.nodeType&&t,Qt=It&&"object"==typeof module&&module&&!module.nodeType&&module,Lt=Qt&&Qt.exports===It?u.Buffer:void 0,Vt=(Lt?Lt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Ht="object"==typeof t&&t&&!t.nodeType&&t,Kt=Ht&&"object"==typeof module&&module&&!module.nodeType&&module,Zt=Kt&&Kt.exports===Ht&&n.process,Xt=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Zt&&Zt.binding&&Zt.binding("util")}catch(t){}}(),Yt=Xt&&Xt.isTypedArray,tr=Yt?function(t){return function(r){return t(r)}}(Yt):function(t){return g(t)&&Gt(t.length)&&!!Wt[v(t)]};function rr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var er=Object.prototype.hasOwnProperty;function nr(t,r,e){var n=t[r];er.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||wt(t,r,e)}var or=/^(?:0|[1-9]\d*)$/;function ur(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&or.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(gr);function jr(t,r){return br(function(t,r,e){return r=hr(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,u=hr(n.length-r,0),i=Array(u);++o1?r[n-1]:void 0,u=n>2?r[2]:void 0;for(o=mr.length>3&&"function"==typeof o?(n--,o):void 0,u&&function(t,r,e){if(!tt(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ur(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],u)&&(o=n<3?void 0:o,n=1),t=Object(t);++e0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},t.chainProcessPromises=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return t.then((function(t){return r(t)}))}),Reflect.apply(t,null,e))}},t.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):Or(t,e)}))}))}),Promise.resolve(!1===r?[]:w(r)?r:{}))},t.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("acknowledge_reply",t,r,e)},t.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},t.createMutation=Ur,t.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Ur(t,r,e,n))},t.createQuery=qr,t.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},t.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("emit_reply",t,r,e)},t.createWsReply=Wr,t.dasherize=function(t){return $(t).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},t.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ar("Unknown "+r+" to extract argument from!")}},t.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Pr(e,r);return n}catch(t){throw new Pr(e,t)}},t.extractSocketPart=Tr,t.extractWsPayload=function(t,r){void 0===r&&(r=H);try{var e,n=W(t);if(!1!==(e=Hr(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ar("payload can not decoded",t)}catch(t){return r("error",t)}},t.formatPayload=Jr,t.getCallMethod=function(t){switch(!0){case t===Sr[0]:return"query";case t===Sr[1]:return"mutation";default:return!1}},t.getConfigValue=function(t,r){return r&&w(r)&&t in r?r[t]:void 0},t.getLogger=function(t){var r=[t];return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];try{window&&window.JSONQL_DEBUG&&Reflect.apply(console.info,console,r.concat(t))}catch(t){}}},t.getMutationFromArgs=Gr,t.getMutationFromPayload=function(t){var r=Dr(t,Gr);if(!1!==r)return r;throw new Nr("[getMutationArgs] Payload is malformed!",t)},t.getNamespace=Qr,t.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},t.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Qr(t),o=e?Ir(r):function(t,r){var e,n={};for(var o in t){var u=t[o];n[o]=u}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},t.getPrivateNamespace=function(t){return t.length>1&&t[0]},t.getQueryFromArgs=Br,t.getQueryFromPayload=function(t){var r=Dr(t,Br);if(!1!==r)return r;throw new Nr("[getQueryArgs] Payload is malformed!",t)},t.getRegex=function(t){switch(!0){case!0===Lr(t):return t;case!0===kr(t):return new RegExp(t);default:return!1}},t.getResolverFromPayload=Mr,t.groupByNamespace=Ir,t.inArray=I,t.injectToFn=function(t,r,e,n){void 0===n&&(n=!1);var o=wr(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t},t.isContract=function(t){return!!function(t){return w(t)&&(V(t,"query")||V(t,"mutation")||V(t,"socket"))}(t)&&t},t.isFunc=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},t.isJsonqlErrorObj=$r,t.isNotEmpty=function(t){return void 0!==t&&!1!==t&&null!==t&&""!==$(t)},t.isObjectHasKey=V,t.isRegExp=Lr,t.isWsReply=Hr,t.logger=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];try{window&&window.DEBUG&&Reflect.apply(console.log,console,t)}catch(t){}},t.nil=H,t.objDefineProps=function(t,r,e,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,r)&&Object.defineProperty(t,r,{set:e,get:null===n?function(){return null}:n}),t},t.objHasProp=wr,t.packError=function(t,r,e,n){var o;void 0===r&&(r="JsonqlError"),void 0===e&&(e=0),void 0===n&&(n="");var u={detail:t,className:r,statusCode:e,message:n};return JSON.stringify(((o={}).error=$r(t)||u,o.TS=[Er()],o))},t.packResult=function(t,e){void 0===e&&(e=!1);var n={};return n.data=t,e&&r(e)&&(e.push(Er()),n.TS=e),JSON.stringify(n)},t.parseJson=L,t.resultHandler=function(t){return V(t,"data")&&!V(t,"error")?t.data:t},t.timestamp=Er,t.toArray=Q,t.toJson=W,t.toPayload=Fr,t.urlParams=xr,Object.defineProperty(t,"__esModule",{value:!0})})); +!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t=t||self).jsonqlUtils={})}(this,(function(t){"use strict";var r=Array.isArray,e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},n="object"==typeof e&&e&&e.Object===Object&&e,o="object"==typeof self&&self&&self.Object===Object&&self,u=n||o||Function("return this")(),i=u.Symbol,a=Object.prototype,c=a.hasOwnProperty,f=a.toString,s=i?i.toStringTag:void 0;var l=Object.prototype.toString;var p=i?i.toStringTag:void 0;function v(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":p&&p in Object(t)?function(t){var r=c.call(t,s),e=t[s];try{t[s]=void 0;var n=!0}catch(t){}var o=f.call(t);return n&&(r?t[s]=e:delete t[s]),o}(t):function(t){return l.call(t)}(t)}var d,y,h=(d=Object.getPrototypeOf,y=Object,function(t){return d(y(t))});function g(t){return null!=t&&"object"==typeof t}var _=Function.prototype,b=Object.prototype,j=_.toString,m=b.hasOwnProperty,O=j.call(Object);function w(t){if(!g(t)||"[object Object]"!=v(t))return!1;var r=h(t);if(null===r)return!0;var e=m.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&j.call(e)==O}var S=i?i.prototype:void 0,P=S?S.toString:void 0;function N(t){if("string"==typeof t)return t;if(r(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var u=Array(o);++n-1;);return e}(o,u),function(t,r){for(var e=t.length;e--&&E(r,t[e],0)>-1;);return e}(o,u)+1).join("")}var I=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return r(t)?t:[t]},L=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},V=function(t,r){try{var e=Object.keys(t);return I(e,r)}catch(t){return!1}},W=function(t){return L("string"==typeof t?t:JSON.stringify(t))},H=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function Z(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var X=Array.prototype.splice;function Y(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},Y.prototype.set=function(t,r){var e=this.__data__,n=Z(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function rt(t){if(!tt(t))return!1;var r=v(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var et,nt=u["__core-js_shared__"],ot=(et=/[^.]+$/.exec(nt&&nt.keys&&nt.keys.IE_PROTO||""))?"Symbol(src)_1."+et:"";var ut=Function.prototype.toString;var it=/^\[object .+?Constructor\]$/,at=Function.prototype,ct=Object.prototype,ft=at.toString,st=ct.hasOwnProperty,lt=RegExp("^"+ft.call(st).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pt(t){return!(!tt(t)||function(t){return!!ot&&ot in t}(t))&&(rt(t)?lt:it).test(function(t){if(null!=t){try{return ut.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function vt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pt(e)?e:void 0}var dt=vt(u,"Map"),yt=vt(Object,"create");var ht=Object.prototype.hasOwnProperty;var gt=Object.prototype.hasOwnProperty;function _t(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Gt(t.length)&&!rt(t)}var It="object"==typeof t&&t&&!t.nodeType&&t,Qt=It&&"object"==typeof module&&module&&!module.nodeType&&module,Lt=Qt&&Qt.exports===It?u.Buffer:void 0,Vt=(Lt?Lt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Ht="object"==typeof t&&t&&!t.nodeType&&t,Kt=Ht&&"object"==typeof module&&module&&!module.nodeType&&module,Zt=Kt&&Kt.exports===Ht&&n.process,Xt=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Zt&&Zt.binding&&Zt.binding("util")}catch(t){}}(),Yt=Xt&&Xt.isTypedArray,tr=Yt?function(t){return function(r){return t(r)}}(Yt):function(t){return g(t)&&Gt(t.length)&&!!Wt[v(t)]};function rr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var er=Object.prototype.hasOwnProperty;function nr(t,r,e){var n=t[r];er.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||wt(t,r,e)}var or=/^(?:0|[1-9]\d*)$/;function ur(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&or.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(gr);function jr(t,r){return br(function(t,r,e){return r=hr(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,u=hr(n.length-r,0),i=Array(u);++o1?r[n-1]:void 0,u=n>2?r[2]:void 0;for(o=mr.length>3&&"function"==typeof o?(n--,o):void 0,u&&function(t,r,e){if(!tt(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ur(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],u)&&(o=n<3?void 0:o,n=1),t=Object(t);++e0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},t.chainProcessPromises=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return t.then((function(t){return r(t)}))}),Reflect.apply(t,null,e))}},t.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):Or(t,e)}))}))}),Promise.resolve(!1===r?[]:w(r)?r:{}))},t.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("acknowledge_reply",t,r,e)},t.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},t.createMutation=Ur,t.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Ur(t,r,e,n))},t.createQuery=qr,t.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},t.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Wr("emit_reply",t,r,e)},t.createWsReply=Wr,t.dasherize=function(t){return $(t).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},t.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ar("Unknown "+r+" to extract argument from!")}},t.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Pr(e,r);return n}catch(t){throw new Pr(e,t)}},t.extractSocketPart=Tr,t.extractWsPayload=function(t,r){void 0===r&&(r=H);try{var e,n=W(t);if(!1!==(e=Hr(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ar("payload can not decoded",t)}catch(t){return r("error",t)}},t.formatPayload=Jr,t.freeze=function(t){return Object.freeze(t)},t.getCallMethod=function(t){switch(!0){case t===Sr[0]:return"query";case t===Sr[1]:return"mutation";default:return!1}},t.getConfigValue=function(t,r){return r&&w(r)&&t in r?r[t]:void 0},t.getLogger=function(t){var r=[t];return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];try{window&&window.JSONQL_DEBUG&&Reflect.apply(console.info,console,r.concat(t))}catch(t){}}},t.getMutationFromArgs=Gr,t.getMutationFromPayload=function(t){var r=Dr(t,Gr);if(!1!==r)return r;throw new Nr("[getMutationArgs] Payload is malformed!",t)},t.getNamespace=Qr,t.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},t.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Qr(t),o=e?Ir(r):function(t,r){var e,n={};for(var o in t){var u=t[o];n[o]=u}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},t.getPrivateNamespace=function(t){return t.length>1&&t[0]},t.getQueryFromArgs=Br,t.getQueryFromPayload=function(t){var r=Dr(t,Br);if(!1!==r)return r;throw new Nr("[getQueryArgs] Payload is malformed!",t)},t.getRegex=function(t){switch(!0){case!0===Lr(t):return t;case!0===kr(t):return new RegExp(t);default:return!1}},t.getResolverFromPayload=Mr,t.groupByNamespace=Ir,t.inArray=I,t.injectToFn=function(t,r,e,n){void 0===n&&(n=!1);var o=wr(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t},t.isContract=function(t){return!!function(t){return w(t)&&(V(t,"query")||V(t,"mutation")||V(t,"socket"))}(t)&&t},t.isFunc=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},t.isJsonqlErrorObj=$r,t.isNotEmpty=function(t){return void 0!==t&&!1!==t&&null!==t&&""!==$(t)},t.isObjectHasKey=V,t.isRegExp=Lr,t.isWsReply=Hr,t.logger=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];try{window&&window.DEBUG&&Reflect.apply(console.log,console,t)}catch(t){}},t.nil=H,t.objDefineProps=function(t,r,e,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,r)&&Object.defineProperty(t,r,{set:e,get:null===n?function(){return null}:n}),t},t.objHasProp=wr,t.packError=function(t,r,e,n){var o;void 0===r&&(r="JsonqlError"),void 0===e&&(e=0),void 0===n&&(n="");var u={detail:t,className:r,statusCode:e,message:n};return JSON.stringify(((o={}).error=$r(t)||u,o.TS=[Er()],o))},t.packResult=function(t,e){void 0===e&&(e=!1);var n={};return n.data=t,e&&r(e)&&(e.push(Er()),n.TS=e),JSON.stringify(n)},t.parseJson=L,t.resultHandler=function(t){return V(t,"data")&&!V(t,"error")?t.data:t},t.timestamp=Er,t.toArray=Q,t.toJson=W,t.toPayload=Fr,t.urlParams=zr,Object.defineProperty(t,"__esModule",{value:!0})})); //# sourceMappingURL=browser.js.map diff --git a/packages/utils/index.js b/packages/utils/index.js index 586d4b54..d1c3487f 100644 --- a/packages/utils/index.js +++ b/packages/utils/index.js @@ -28,6 +28,7 @@ import { isFunc, nil, assign, + freeze, // params-api toPayload, formatPayload, @@ -131,6 +132,7 @@ export { isFunc, nil, assign, + freeze, // params-api toPayload, formatPayload, diff --git a/packages/utils/main.js b/packages/utils/main.js index beeba934..2da97349 100644 --- a/packages/utils/main.js +++ b/packages/utils/main.js @@ -1,2 +1,2 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t,r=(t=require("fs"))&&"object"==typeof t&&"default"in t?t.default:t,e=require("path"),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,u="object"==typeof self&&self&&self.Object===Object&&self,a=i||u||Function("return this")(),f=a.Symbol,s=Object.prototype,c=s.hasOwnProperty,h=s.toString,p=f?f.toStringTag:void 0;var l=Object.prototype.toString;var g=f?f.toStringTag:void 0;function y(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":g&&g in Object(t)?function(t){var r=c.call(t,p),e=t[p];try{t[p]=void 0;var n=!0}catch(t){}var o=h.call(t);return n&&(r?t[p]=e:delete t[p]),o}(t):function(t){return l.call(t)}(t)}var v,d,_=(v=Object.getPrototypeOf,d=Object,function(t){return v(d(t))});function b(t){return null!=t&&"object"==typeof t}var w=Function.prototype,m=Object.prototype,A=w.toString,E=m.hasOwnProperty,x=A.call(Object);function j(t){if(!b(t)||"[object Object]"!=y(t))return!1;var r=_(t);if(null===r)return!0;var e=E.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&A.call(e)==x}var P=f?f.prototype:void 0,R=P?P.toString:void 0;function O(t){if("string"==typeof t)return t;if(n(t))return function(t,r){for(var e=-1,n=null==t?0:t.length,o=Array(n);++e=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var i=Array(o);++n-1;);return e}(o,i),function(t,r){for(var e=t.length;e--&&U(r,t[e],0)>-1;);return e}(o,i)+1).join("")}var G=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return n(t)?t:[t]},V=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},H=function(t,r){try{var e=Object.keys(t);return G(e,r)}catch(t){return!1}},W=function(t){return V("string"==typeof t?t:JSON.stringify(t))},Z=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function X(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var tt=Array.prototype.splice;function rt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},rt.prototype.set=function(t,r){var e=this.__data__,n=X(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function nt(t){if(!et(t))return!1;var r=y(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var ot,it=a["__core-js_shared__"],ut=(ot=/[^.]+$/.exec(it&&it.keys&&it.keys.IE_PROTO||""))?"Symbol(src)_1."+ot:"";var at=Function.prototype.toString;var ft=/^\[object .+?Constructor\]$/,st=Function.prototype,ct=Object.prototype,ht=st.toString,pt=ct.hasOwnProperty,lt=RegExp("^"+ht.call(pt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function gt(t){return!(!et(t)||function(t){return!!ut&&ut in t}(t))&&(nt(t)?lt:ft).test(function(t){if(null!=t){try{return at.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function yt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return gt(e)?e:void 0}var vt=yt(a,"Map"),dt=yt(Object,"create");var _t=Object.prototype.hasOwnProperty;var bt=Object.prototype.hasOwnProperty;function wt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Jt(t.length)&&!nt(t)}var Gt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Qt=Gt&&"object"==typeof module&&module&&!module.nodeType&&module,Vt=Qt&&Qt.exports===Gt?a.Buffer:void 0,Ht=(Vt?Vt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Zt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Kt=Zt&&"object"==typeof module&&module&&!module.nodeType&&module,Xt=Kt&&Kt.exports===Zt&&i.process,tr=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Xt&&Xt.binding&&Xt.binding("util")}catch(t){}}(),rr=tr&&tr.isTypedArray,er=rr?function(t){return function(r){return t(r)}}(rr):function(t){return b(t)&&Jt(t.length)&&!!Wt[y(t)]};function nr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var or=Object.prototype.hasOwnProperty;function ir(t,r,e){var n=t[r];or.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||jt(t,r,e)}var ur=/^(?:0|[1-9]\d*)$/;function ar(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&ur.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(br);function Ar(t,r){return mr(function(t,r,e){return r=_r(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,i=_r(n.length-r,0),u=Array(i);++o1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=Er.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!et(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ar(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e>18&63]+re[o>>12&63]+re[o>>6&63]+re[63&o]);return i.join("")}function ae(t){var r;oe||ie();for(var e=t.length,n=e%3,o="",i=[],u=0,a=e-n;ua?a:u+16383));return 1===n?(r=t[e-1],o+=re[r>>2],o+=re[r<<4&63],o+="=="):2===n&&(r=(t[e-2]<<8)+t[e-1],o+=re[r>>10],o+=re[r>>4&63],o+=re[r<<2&63],o+="="),i.push(o),i.join("")}function fe(t,r,e,n,o){var i,u,a=8*o-n-1,f=(1<>1,c=-7,h=e?o-1:0,p=e?-1:1,l=t[r+h];for(h+=p,i=l&(1<<-c)-1,l>>=-c,c+=a;c>0;i=256*i+t[r+h],h+=p,c-=8);for(u=i&(1<<-c)-1,i>>=-c,c+=n;c>0;u=256*u+t[r+h],h+=p,c-=8);if(0===i)i=1-s;else{if(i===f)return u?NaN:1/0*(l?-1:1);u+=Math.pow(2,n),i-=s}return(l?-1:1)*u*Math.pow(2,i-n)}function se(t,r,e,n,o,i){var u,a,f,s=8*i-o-1,c=(1<>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,l=n?0:i-1,g=n?1:-1,y=r<0||0===r&&1/r<0?1:0;for(r=Math.abs(r),isNaN(r)||r===1/0?(a=isNaN(r)?1:0,u=c):(u=Math.floor(Math.log(r)/Math.LN2),r*(f=Math.pow(2,-u))<1&&(u--,f*=2),(r+=u+h>=1?p/f:p*Math.pow(2,1-h))*f>=2&&(u++,f/=2),u+h>=c?(a=0,u=c):u+h>=1?(a=(r*f-1)*Math.pow(2,o),u+=h):(a=r*Math.pow(2,h-1)*Math.pow(2,o),u=0));o>=8;t[e+l]=255&a,l+=g,a/=256,o-=8);for(u=u<0;t[e+l]=255&u,l+=g,u/=256,s-=8);t[e+l-g]|=128*y}var ce={}.toString,he=Array.isArray||function(t){return"[object Array]"==ce.call(t)};function pe(){return ge.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function le(t,r){if(pe()=pe())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+pe().toString(16)+" bytes");return 0|t}function we(t){return!(null==t||!t._isBuffer)}function me(t,r){if(we(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var e=t.length;if(0===e)return 0;for(var n=!1;;)switch(r){case"ascii":case"latin1":case"binary":return e;case"utf8":case"utf-8":case void 0:return Qe(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*e;case"hex":return e>>>1;case"base64":return Ve(t).length;default:if(n)return Qe(t).length;r=(""+r).toLowerCase(),n=!0}}function Ae(t,r,e){var n=!1;if((void 0===r||r<0)&&(r=0),r>this.length)return"";if((void 0===e||e>this.length)&&(e=this.length),e<=0)return"";if((e>>>=0)<=(r>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return Ye(this,r,e);case"utf8":case"utf-8":return Ne(this,r,e);case"ascii":return Ie(this,r,e);case"latin1":case"binary":return Ce(this,r,e);case"base64":return Be(this,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Me(this,r,e);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function Ee(t,r,e){var n=t[r];t[r]=t[e],t[e]=n}function xe(t,r,e,n,o){if(0===t.length)return-1;if("string"==typeof e?(n=e,e=0):e>2147483647?e=2147483647:e<-2147483648&&(e=-2147483648),e=+e,isNaN(e)&&(e=o?0:t.length-1),e<0&&(e=t.length+e),e>=t.length){if(o)return-1;e=t.length-1}else if(e<0){if(!o)return-1;e=0}if("string"==typeof r&&(r=ge.from(r,n)),we(r))return 0===r.length?-1:je(t,r,e,n,o);if("number"==typeof r)return r&=255,ge.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,r,e):Uint8Array.prototype.lastIndexOf.call(t,r,e):je(t,[r],e,n,o);throw new TypeError("val must be string, number or Buffer")}function je(t,r,e,n,o){var i,u=1,a=t.length,f=r.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||r.length<2)return-1;u=2,a/=2,f/=2,e/=2}function s(t,r){return 1===u?t[r]:t.readUInt16BE(r*u)}if(o){var c=-1;for(i=e;ia&&(e=a-f),i=e;i>=0;i--){for(var h=!0,p=0;po&&(n=o):n=o;var i=r.length;if(i%2!=0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var u=0;u>8,o=e%256,i.push(o),i.push(n);return i}(r,t.length-e),t,e,n)}function Be(t,r,e){return 0===r&&e===t.length?ae(t):ae(t.slice(r,e))}function Ne(t,r,e){e=Math.min(t.length,e);for(var n=[],o=r;o239?4:s>223?3:s>191?2:1;if(o+h<=e)switch(h){case 1:s<128&&(c=s);break;case 2:128==(192&(i=t[o+1]))&&(f=(31&s)<<6|63&i)>127&&(c=f);break;case 3:i=t[o+1],u=t[o+2],128==(192&i)&&128==(192&u)&&(f=(15&s)<<12|(63&i)<<6|63&u)>2047&&(f<55296||f>57343)&&(c=f);break;case 4:i=t[o+1],u=t[o+2],a=t[o+3],128==(192&i)&&128==(192&u)&&128==(192&a)&&(f=(15&s)<<18|(63&i)<<12|(63&u)<<6|63&a)>65535&&f<1114112&&(c=f)}null===c?(c=65533,h=1):c>65535&&(c-=65536,n.push(c>>>10&1023|55296),c=56320|1023&c),n.push(c),o+=h}return function(t){var r=t.length;if(r<=4096)return String.fromCharCode.apply(String,t);var e="",n=0;for(;n0&&(t=this.toString("hex",0,50).match(/.{2}/g).join(" "),this.length>50&&(t+=" ... ")),""},ge.prototype.compare=function(t,r,e,n,o){if(!we(t))throw new TypeError("Argument must be a Buffer");if(void 0===r&&(r=0),void 0===e&&(e=t?t.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),r<0||e>t.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&r>=e)return 0;if(n>=o)return-1;if(r>=e)return 1;if(this===t)return 0;for(var i=(o>>>=0)-(n>>>=0),u=(e>>>=0)-(r>>>=0),a=Math.min(i,u),f=this.slice(n,o),s=t.slice(r,e),c=0;co)&&(e=o),t.length>0&&(e<0||r<0)||r>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return Pe(this,t,r,e);case"utf8":case"utf-8":return Re(this,t,r,e);case"ascii":return Oe(this,t,r,e);case"latin1":case"binary":return Te(this,t,r,e);case"base64":return Se(this,t,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Ue(this,t,r,e);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},ge.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Ie(t,r,e){var n="";e=Math.min(t.length,e);for(var o=r;on)&&(e=n);for(var o="",i=r;ie)throw new RangeError("Trying to access beyond buffer length")}function De(t,r,e,n,o,i){if(!we(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(r>o||rt.length)throw new RangeError("Index out of range")}function Le(t,r,e,n){r<0&&(r=65535+r+1);for(var o=0,i=Math.min(t.length-e,2);o>>8*(n?o:1-o)}function ze(t,r,e,n){r<0&&(r=4294967295+r+1);for(var o=0,i=Math.min(t.length-e,4);o>>8*(n?o:3-o)&255}function Fe(t,r,e,n,o,i){if(e+n>t.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function qe(t,r,e,n,o){return o||Fe(t,0,e,4),se(t,r,e,n,23,4),e+4}function Je(t,r,e,n,o){return o||Fe(t,0,e,8),se(t,r,e,n,52,8),e+8}ge.prototype.slice=function(t,r){var e,n=this.length;if((t=~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),(r=void 0===r?n:~~r)<0?(r+=n)<0&&(r=0):r>n&&(r=n),r0&&(o*=256);)n+=this[t+--r]*o;return n},ge.prototype.readUInt8=function(t,r){return r||ke(t,1,this.length),this[t]},ge.prototype.readUInt16LE=function(t,r){return r||ke(t,2,this.length),this[t]|this[t+1]<<8},ge.prototype.readUInt16BE=function(t,r){return r||ke(t,2,this.length),this[t]<<8|this[t+1]},ge.prototype.readUInt32LE=function(t,r){return r||ke(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},ge.prototype.readUInt32BE=function(t,r){return r||ke(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},ge.prototype.readIntLE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=this[t],o=1,i=0;++i=(o*=128)&&(n-=Math.pow(2,8*r)),n},ge.prototype.readIntBE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=r,o=1,i=this[t+--n];n>0&&(o*=256);)i+=this[t+--n]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*r)),i},ge.prototype.readInt8=function(t,r){return r||ke(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},ge.prototype.readInt16LE=function(t,r){r||ke(t,2,this.length);var e=this[t]|this[t+1]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt16BE=function(t,r){r||ke(t,2,this.length);var e=this[t+1]|this[t]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt32LE=function(t,r){return r||ke(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},ge.prototype.readInt32BE=function(t,r){return r||ke(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},ge.prototype.readFloatLE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!0,23,4)},ge.prototype.readFloatBE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!1,23,4)},ge.prototype.readDoubleLE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!0,52,8)},ge.prototype.readDoubleBE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!1,52,8)},ge.prototype.writeUIntLE=function(t,r,e,n){(t=+t,r|=0,e|=0,n)||De(this,t,r,e,Math.pow(2,8*e)-1,0);var o=1,i=0;for(this[r]=255&t;++i=0&&(i*=256);)this[r+o]=t/i&255;return r+e},ge.prototype.writeUInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,255,0),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[r]=255&t,r+1},ge.prototype.writeUInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeUInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeUInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r+3]=t>>>24,this[r+2]=t>>>16,this[r+1]=t>>>8,this[r]=255&t):ze(this,t,r,!0),r+4},ge.prototype.writeUInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeIntLE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=0,u=1,a=0;for(this[r]=255&t;++i>0)-a&255;return r+e},ge.prototype.writeIntBE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=e-1,u=1,a=0;for(this[r+i]=255&t;--i>=0&&(u*=256);)t<0&&0===a&&0!==this[r+i+1]&&(a=1),this[r+i]=(t/u>>0)-a&255;return r+e},ge.prototype.writeInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,127,-128),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[r]=255&t,r+1},ge.prototype.writeInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):Le(this,t,r,!0),r+2},ge.prototype.writeInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):Le(this,t,r,!1),r+2},ge.prototype.writeInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8,this[r+2]=t>>>16,this[r+3]=t>>>24):ze(this,t,r,!0),r+4},ge.prototype.writeInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):ze(this,t,r,!1),r+4},ge.prototype.writeFloatLE=function(t,r,e){return qe(this,t,r,!0,e)},ge.prototype.writeFloatBE=function(t,r,e){return qe(this,t,r,!1,e)},ge.prototype.writeDoubleLE=function(t,r,e){return Je(this,t,r,!0,e)},ge.prototype.writeDoubleBE=function(t,r,e){return Je(this,t,r,!1,e)},ge.prototype.copy=function(t,r,e,n){if(e||(e=0),n||0===n||(n=this.length),r>=t.length&&(r=t.length),r||(r=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-r=0;--o)t[o+r]=this[o+e];else if(i<1e3||!ge.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,e=void 0===e?this.length:e>>>0,t||(t=0),"number"==typeof t)for(i=r;i55295&&e<57344){if(!o){if(e>56319){(r-=3)>-1&&i.push(239,191,189);continue}if(u+1===n){(r-=3)>-1&&i.push(239,191,189);continue}o=e;continue}if(e<56320){(r-=3)>-1&&i.push(239,191,189),o=e;continue}e=65536+(o-55296<<10|e-56320)}else o&&(r-=3)>-1&&i.push(239,191,189);if(o=null,e<128){if((r-=1)<0)break;i.push(e)}else if(e<2048){if((r-=2)<0)break;i.push(e>>6|192,63&e|128)}else if(e<65536){if((r-=3)<0)break;i.push(e>>12|224,e>>6&63|128,63&e|128)}else{if(!(e<1114112))throw new Error("Invalid code point");if((r-=4)<0)break;i.push(e>>18|240,e>>12&63|128,e>>6&63|128,63&e|128)}}return i}function Ve(t){return function(t){var r,e,n,o,i,u;oe||ie();var a=t.length;if(a%4>0)throw new Error("Invalid string. Length must be a multiple of 4");i="="===t[a-2]?2:"="===t[a-1]?1:0,u=new ne(3*a/4-i),n=i>0?a-4:a;var f=0;for(r=0,e=0;r>16&255,u[f++]=o>>8&255,u[f++]=255&o;return 2===i?(o=ee[t.charCodeAt(r)]<<2|ee[t.charCodeAt(r+1)]>>4,u[f++]=255&o):1===i&&(o=ee[t.charCodeAt(r)]<<10|ee[t.charCodeAt(r+1)]<<4|ee[t.charCodeAt(r+2)]>>2,u[f++]=o>>8&255,u[f++]=255&o),u}(function(t){if((t=function(t){if(t.trim)return t.trim();return t.replace(/^\s+|\s+$/g,"")}(t).replace($e,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function He(t,r,e,n){for(var o=0;o=r.length||o>=t.length);++o)r[o+e]=t[o];return o}function We(t){return null!=t&&(!!t._isBuffer||Ze(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&Ze(t.slice(0,0))}(t))}function Ze(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}var Ke=function(t,r){if(r instanceof Error){var e={};return Object.getOwnPropertyNames(r).forEach((function(t){e[t]=r[t]})),e}return r};var Xe=function(t,r){try{var e=t.headers.accept.split(",");return r?e.filter((function(t){return t===r})):e}catch(t){return[]}},tn=function(t,r){return!!Xe(t,r).length},rn=function(t,r){return t.path===r.jsonqlPath};exports.VERSION="1.2.3",exports.assign=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return Reflect.apply(Object.assign,Object,t)},exports.buff=function(t,r){return void 0===r&&(r="base64"),We(t)?t:new ge.from(t,r)},exports.cacheBurst=Yr,exports.cacheBurstUrl=function(t){return Cr(t,Yr())},exports.chainFns=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},exports.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):xr(t,e)}))}))}),Promise.resolve(!1===r?[]:j(r)?r:{}))},exports.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("acknowledge_reply",t,r,e)},exports.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},exports.createMutation=Jr,exports.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Jr(t,r,e,n))},exports.createQuery=qr,exports.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},exports.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("emit_reply",t,r,e)},exports.createWsReply=Xr,exports.dasherize=Ir,exports.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ur("Unknown "+r+" to extract argument from!")}},exports.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Tr(e,r);return n}catch(t){throw new Tr(e,t)}},exports.extractSocketPart=Br,exports.extractWsPayload=function(t,r){void 0===r&&(r=Z);try{var e,n=W(t);if(!1!==(e=te(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ur("payload can not decoded",t)}catch(t){return r("error",t)}},exports.findFromContract=function(t,e,n){return!!(n[t]&&n[t][e]&&n[t][e].file&&r.existsSync(n[t][e].file))&&n[t][e].file},exports.formatPayload=Lr,exports.getCallMethod=function(t){switch(!0){case t===Rr[0]:return"query";case t===Rr[1]:return"mutation";default:return!1}},exports.getConfigValue=function(t,r){return r&&j(r)&&t in r?r[t]:void 0},exports.getDocLen=function(t){return ge.byteLength(t,"utf8")},exports.getMutationFromArgs=Qr,exports.getMutationFromPayload=function(t){var r=Gr(t,Qr);if(!1!==r)return r;throw new Sr("[getMutationArgs] Payload is malformed!",t)},exports.getNamespace=Wr,exports.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},exports.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Wr(t),o=e?Hr(r):function(t,r){var e,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},exports.getPathToFn=function(t,n,o){var i=o.resolverDir,u=Ir(t),a=[];o.contract&&o.contract[n]&&o.contract[n].path&&a.push(o.contract[n].path),a.push(e.join(i,n,u,[Or,Pr].join("."))),a.push(e.join(i,n,[u,Pr].join(".")));for(var f=a.length,s=0;s=n?t:function(t,r,e){var n=-1,o=t.length;r<0&&(r=-r>o?0:o+r),(e=e>o?o:e)<0&&(e+=o),o=r>e?0:e-r>>>0,r>>>=0;for(var i=Array(o);++n-1;);return e}(o,i),function(t,r){for(var e=t.length;e--&&U(r,t[e],0)>-1;);return e}(o,i)+1).join("")}var G=function(t,r){return!!t.filter((function(t){return t===r})).length},Q=function(t){return n(t)?t:[t]},V=function(t,r){void 0===r&&(r=!0);try{return JSON.parse(t)}catch(e){if(r)return t;throw new Error(e)}},H=function(t,r){try{var e=Object.keys(t);return G(e,r)}catch(t){return!1}},W=function(t){return V("string"==typeof t?t:JSON.stringify(t))},Z=function(){return!1};function K(t,r){return t===r||t!=t&&r!=r}function X(t,r){for(var e=t.length;e--;)if(K(t[e][0],r))return e;return-1}var tt=Array.prototype.splice;function rt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},rt.prototype.set=function(t,r){var e=this.__data__,n=X(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};function nt(t){if(!et(t))return!1;var r=y(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}var ot,it=a["__core-js_shared__"],ut=(ot=/[^.]+$/.exec(it&&it.keys&&it.keys.IE_PROTO||""))?"Symbol(src)_1."+ot:"";var at=Function.prototype.toString;var ft=/^\[object .+?Constructor\]$/,st=Function.prototype,ct=Object.prototype,ht=st.toString,pt=ct.hasOwnProperty,lt=RegExp("^"+ht.call(pt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function gt(t){return!(!et(t)||function(t){return!!ut&&ut in t}(t))&&(nt(t)?lt:ft).test(function(t){if(null!=t){try{return at.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function yt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return gt(e)?e:void 0}var vt=yt(a,"Map"),dt=yt(Object,"create");var _t=Object.prototype.hasOwnProperty;var bt=Object.prototype.hasOwnProperty;function wt(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1&&t%1==0&&t<=9007199254740991}function $t(t){return null!=t&&Jt(t.length)&&!nt(t)}var Gt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Qt=Gt&&"object"==typeof module&&module&&!module.nodeType&&module,Vt=Qt&&Qt.exports===Gt?a.Buffer:void 0,Ht=(Vt?Vt.isBuffer:void 0)||function(){return!1},Wt={};Wt["[object Float32Array]"]=Wt["[object Float64Array]"]=Wt["[object Int8Array]"]=Wt["[object Int16Array]"]=Wt["[object Int32Array]"]=Wt["[object Uint8Array]"]=Wt["[object Uint8ClampedArray]"]=Wt["[object Uint16Array]"]=Wt["[object Uint32Array]"]=!0,Wt["[object Arguments]"]=Wt["[object Array]"]=Wt["[object ArrayBuffer]"]=Wt["[object Boolean]"]=Wt["[object DataView]"]=Wt["[object Date]"]=Wt["[object Error]"]=Wt["[object Function]"]=Wt["[object Map]"]=Wt["[object Number]"]=Wt["[object Object]"]=Wt["[object RegExp]"]=Wt["[object Set]"]=Wt["[object String]"]=Wt["[object WeakMap]"]=!1;var Zt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Kt=Zt&&"object"==typeof module&&module&&!module.nodeType&&module,Xt=Kt&&Kt.exports===Zt&&i.process,tr=function(){try{var t=Kt&&Kt.require&&Kt.require("util").types;return t||Xt&&Xt.binding&&Xt.binding("util")}catch(t){}}(),rr=tr&&tr.isTypedArray,er=rr?function(t){return function(r){return t(r)}}(rr):function(t){return b(t)&&Jt(t.length)&&!!Wt[y(t)]};function nr(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var or=Object.prototype.hasOwnProperty;function ir(t,r,e){var n=t[r];or.call(t,r)&&K(n,e)&&(void 0!==e||r in t)||jt(t,r,e)}var ur=/^(?:0|[1-9]\d*)$/;function ar(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&ur.test(t))&&t>-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(br);function Ar(t,r){return mr(function(t,r,e){return r=_r(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,i=_r(n.length-r,0),u=Array(i);++o1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=Er.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!et(e))return!1;var n=typeof r;return!!("number"==n?$t(e)&&ar(r,e.length):"string"==n&&r in e)&&K(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e>18&63]+re[o>>12&63]+re[o>>6&63]+re[63&o]);return i.join("")}function ae(t){var r;oe||ie();for(var e=t.length,n=e%3,o="",i=[],u=0,a=e-n;ua?a:u+16383));return 1===n?(r=t[e-1],o+=re[r>>2],o+=re[r<<4&63],o+="=="):2===n&&(r=(t[e-2]<<8)+t[e-1],o+=re[r>>10],o+=re[r>>4&63],o+=re[r<<2&63],o+="="),i.push(o),i.join("")}function fe(t,r,e,n,o){var i,u,a=8*o-n-1,f=(1<>1,c=-7,h=e?o-1:0,p=e?-1:1,l=t[r+h];for(h+=p,i=l&(1<<-c)-1,l>>=-c,c+=a;c>0;i=256*i+t[r+h],h+=p,c-=8);for(u=i&(1<<-c)-1,i>>=-c,c+=n;c>0;u=256*u+t[r+h],h+=p,c-=8);if(0===i)i=1-s;else{if(i===f)return u?NaN:1/0*(l?-1:1);u+=Math.pow(2,n),i-=s}return(l?-1:1)*u*Math.pow(2,i-n)}function se(t,r,e,n,o,i){var u,a,f,s=8*i-o-1,c=(1<>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,l=n?0:i-1,g=n?1:-1,y=r<0||0===r&&1/r<0?1:0;for(r=Math.abs(r),isNaN(r)||r===1/0?(a=isNaN(r)?1:0,u=c):(u=Math.floor(Math.log(r)/Math.LN2),r*(f=Math.pow(2,-u))<1&&(u--,f*=2),(r+=u+h>=1?p/f:p*Math.pow(2,1-h))*f>=2&&(u++,f/=2),u+h>=c?(a=0,u=c):u+h>=1?(a=(r*f-1)*Math.pow(2,o),u+=h):(a=r*Math.pow(2,h-1)*Math.pow(2,o),u=0));o>=8;t[e+l]=255&a,l+=g,a/=256,o-=8);for(u=u<0;t[e+l]=255&u,l+=g,u/=256,s-=8);t[e+l-g]|=128*y}var ce={}.toString,he=Array.isArray||function(t){return"[object Array]"==ce.call(t)};function pe(){return ge.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function le(t,r){if(pe()=pe())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+pe().toString(16)+" bytes");return 0|t}function we(t){return!(null==t||!t._isBuffer)}function me(t,r){if(we(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var e=t.length;if(0===e)return 0;for(var n=!1;;)switch(r){case"ascii":case"latin1":case"binary":return e;case"utf8":case"utf-8":case void 0:return Qe(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*e;case"hex":return e>>>1;case"base64":return Ve(t).length;default:if(n)return Qe(t).length;r=(""+r).toLowerCase(),n=!0}}function Ae(t,r,e){var n=!1;if((void 0===r||r<0)&&(r=0),r>this.length)return"";if((void 0===e||e>this.length)&&(e=this.length),e<=0)return"";if((e>>>=0)<=(r>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return Ye(this,r,e);case"utf8":case"utf-8":return Ne(this,r,e);case"ascii":return Ie(this,r,e);case"latin1":case"binary":return Ce(this,r,e);case"base64":return Be(this,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Me(this,r,e);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function Ee(t,r,e){var n=t[r];t[r]=t[e],t[e]=n}function xe(t,r,e,n,o){if(0===t.length)return-1;if("string"==typeof e?(n=e,e=0):e>2147483647?e=2147483647:e<-2147483648&&(e=-2147483648),e=+e,isNaN(e)&&(e=o?0:t.length-1),e<0&&(e=t.length+e),e>=t.length){if(o)return-1;e=t.length-1}else if(e<0){if(!o)return-1;e=0}if("string"==typeof r&&(r=ge.from(r,n)),we(r))return 0===r.length?-1:je(t,r,e,n,o);if("number"==typeof r)return r&=255,ge.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,r,e):Uint8Array.prototype.lastIndexOf.call(t,r,e):je(t,[r],e,n,o);throw new TypeError("val must be string, number or Buffer")}function je(t,r,e,n,o){var i,u=1,a=t.length,f=r.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||r.length<2)return-1;u=2,a/=2,f/=2,e/=2}function s(t,r){return 1===u?t[r]:t.readUInt16BE(r*u)}if(o){var c=-1;for(i=e;ia&&(e=a-f),i=e;i>=0;i--){for(var h=!0,p=0;po&&(n=o):n=o;var i=r.length;if(i%2!=0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var u=0;u>8,o=e%256,i.push(o),i.push(n);return i}(r,t.length-e),t,e,n)}function Be(t,r,e){return 0===r&&e===t.length?ae(t):ae(t.slice(r,e))}function Ne(t,r,e){e=Math.min(t.length,e);for(var n=[],o=r;o239?4:s>223?3:s>191?2:1;if(o+h<=e)switch(h){case 1:s<128&&(c=s);break;case 2:128==(192&(i=t[o+1]))&&(f=(31&s)<<6|63&i)>127&&(c=f);break;case 3:i=t[o+1],u=t[o+2],128==(192&i)&&128==(192&u)&&(f=(15&s)<<12|(63&i)<<6|63&u)>2047&&(f<55296||f>57343)&&(c=f);break;case 4:i=t[o+1],u=t[o+2],a=t[o+3],128==(192&i)&&128==(192&u)&&128==(192&a)&&(f=(15&s)<<18|(63&i)<<12|(63&u)<<6|63&a)>65535&&f<1114112&&(c=f)}null===c?(c=65533,h=1):c>65535&&(c-=65536,n.push(c>>>10&1023|55296),c=56320|1023&c),n.push(c),o+=h}return function(t){var r=t.length;if(r<=4096)return String.fromCharCode.apply(String,t);var e="",n=0;for(;n0&&(t=this.toString("hex",0,50).match(/.{2}/g).join(" "),this.length>50&&(t+=" ... ")),""},ge.prototype.compare=function(t,r,e,n,o){if(!we(t))throw new TypeError("Argument must be a Buffer");if(void 0===r&&(r=0),void 0===e&&(e=t?t.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),r<0||e>t.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&r>=e)return 0;if(n>=o)return-1;if(r>=e)return 1;if(this===t)return 0;for(var i=(o>>>=0)-(n>>>=0),u=(e>>>=0)-(r>>>=0),a=Math.min(i,u),f=this.slice(n,o),s=t.slice(r,e),c=0;co)&&(e=o),t.length>0&&(e<0||r<0)||r>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return Pe(this,t,r,e);case"utf8":case"utf-8":return Re(this,t,r,e);case"ascii":return Oe(this,t,r,e);case"latin1":case"binary":return Te(this,t,r,e);case"base64":return Se(this,t,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Ue(this,t,r,e);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},ge.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Ie(t,r,e){var n="";e=Math.min(t.length,e);for(var o=r;on)&&(e=n);for(var o="",i=r;ie)throw new RangeError("Trying to access beyond buffer length")}function De(t,r,e,n,o,i){if(!we(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(r>o||rt.length)throw new RangeError("Index out of range")}function ze(t,r,e,n){r<0&&(r=65535+r+1);for(var o=0,i=Math.min(t.length-e,2);o>>8*(n?o:1-o)}function Le(t,r,e,n){r<0&&(r=4294967295+r+1);for(var o=0,i=Math.min(t.length-e,4);o>>8*(n?o:3-o)&255}function Fe(t,r,e,n,o,i){if(e+n>t.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function qe(t,r,e,n,o){return o||Fe(t,0,e,4),se(t,r,e,n,23,4),e+4}function Je(t,r,e,n,o){return o||Fe(t,0,e,8),se(t,r,e,n,52,8),e+8}ge.prototype.slice=function(t,r){var e,n=this.length;if((t=~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),(r=void 0===r?n:~~r)<0?(r+=n)<0&&(r=0):r>n&&(r=n),r0&&(o*=256);)n+=this[t+--r]*o;return n},ge.prototype.readUInt8=function(t,r){return r||ke(t,1,this.length),this[t]},ge.prototype.readUInt16LE=function(t,r){return r||ke(t,2,this.length),this[t]|this[t+1]<<8},ge.prototype.readUInt16BE=function(t,r){return r||ke(t,2,this.length),this[t]<<8|this[t+1]},ge.prototype.readUInt32LE=function(t,r){return r||ke(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},ge.prototype.readUInt32BE=function(t,r){return r||ke(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},ge.prototype.readIntLE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=this[t],o=1,i=0;++i=(o*=128)&&(n-=Math.pow(2,8*r)),n},ge.prototype.readIntBE=function(t,r,e){t|=0,r|=0,e||ke(t,r,this.length);for(var n=r,o=1,i=this[t+--n];n>0&&(o*=256);)i+=this[t+--n]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*r)),i},ge.prototype.readInt8=function(t,r){return r||ke(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},ge.prototype.readInt16LE=function(t,r){r||ke(t,2,this.length);var e=this[t]|this[t+1]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt16BE=function(t,r){r||ke(t,2,this.length);var e=this[t+1]|this[t]<<8;return 32768&e?4294901760|e:e},ge.prototype.readInt32LE=function(t,r){return r||ke(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},ge.prototype.readInt32BE=function(t,r){return r||ke(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},ge.prototype.readFloatLE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!0,23,4)},ge.prototype.readFloatBE=function(t,r){return r||ke(t,4,this.length),fe(this,t,!1,23,4)},ge.prototype.readDoubleLE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!0,52,8)},ge.prototype.readDoubleBE=function(t,r){return r||ke(t,8,this.length),fe(this,t,!1,52,8)},ge.prototype.writeUIntLE=function(t,r,e,n){(t=+t,r|=0,e|=0,n)||De(this,t,r,e,Math.pow(2,8*e)-1,0);var o=1,i=0;for(this[r]=255&t;++i=0&&(i*=256);)this[r+o]=t/i&255;return r+e},ge.prototype.writeUInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,255,0),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[r]=255&t,r+1},ge.prototype.writeUInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):ze(this,t,r,!0),r+2},ge.prototype.writeUInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,65535,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):ze(this,t,r,!1),r+2},ge.prototype.writeUInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r+3]=t>>>24,this[r+2]=t>>>16,this[r+1]=t>>>8,this[r]=255&t):Le(this,t,r,!0),r+4},ge.prototype.writeUInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,4294967295,0),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):Le(this,t,r,!1),r+4},ge.prototype.writeIntLE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=0,u=1,a=0;for(this[r]=255&t;++i>0)-a&255;return r+e},ge.prototype.writeIntBE=function(t,r,e,n){if(t=+t,r|=0,!n){var o=Math.pow(2,8*e-1);De(this,t,r,e,o-1,-o)}var i=e-1,u=1,a=0;for(this[r+i]=255&t;--i>=0&&(u*=256);)t<0&&0===a&&0!==this[r+i+1]&&(a=1),this[r+i]=(t/u>>0)-a&255;return r+e},ge.prototype.writeInt8=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,1,127,-128),ge.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[r]=255&t,r+1},ge.prototype.writeInt16LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8):ze(this,t,r,!0),r+2},ge.prototype.writeInt16BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,2,32767,-32768),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>8,this[r+1]=255&t):ze(this,t,r,!1),r+2},ge.prototype.writeInt32LE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),ge.TYPED_ARRAY_SUPPORT?(this[r]=255&t,this[r+1]=t>>>8,this[r+2]=t>>>16,this[r+3]=t>>>24):Le(this,t,r,!0),r+4},ge.prototype.writeInt32BE=function(t,r,e){return t=+t,r|=0,e||De(this,t,r,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),ge.TYPED_ARRAY_SUPPORT?(this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t):Le(this,t,r,!1),r+4},ge.prototype.writeFloatLE=function(t,r,e){return qe(this,t,r,!0,e)},ge.prototype.writeFloatBE=function(t,r,e){return qe(this,t,r,!1,e)},ge.prototype.writeDoubleLE=function(t,r,e){return Je(this,t,r,!0,e)},ge.prototype.writeDoubleBE=function(t,r,e){return Je(this,t,r,!1,e)},ge.prototype.copy=function(t,r,e,n){if(e||(e=0),n||0===n||(n=this.length),r>=t.length&&(r=t.length),r||(r=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-r=0;--o)t[o+r]=this[o+e];else if(i<1e3||!ge.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,e=void 0===e?this.length:e>>>0,t||(t=0),"number"==typeof t)for(i=r;i55295&&e<57344){if(!o){if(e>56319){(r-=3)>-1&&i.push(239,191,189);continue}if(u+1===n){(r-=3)>-1&&i.push(239,191,189);continue}o=e;continue}if(e<56320){(r-=3)>-1&&i.push(239,191,189),o=e;continue}e=65536+(o-55296<<10|e-56320)}else o&&(r-=3)>-1&&i.push(239,191,189);if(o=null,e<128){if((r-=1)<0)break;i.push(e)}else if(e<2048){if((r-=2)<0)break;i.push(e>>6|192,63&e|128)}else if(e<65536){if((r-=3)<0)break;i.push(e>>12|224,e>>6&63|128,63&e|128)}else{if(!(e<1114112))throw new Error("Invalid code point");if((r-=4)<0)break;i.push(e>>18|240,e>>12&63|128,e>>6&63|128,63&e|128)}}return i}function Ve(t){return function(t){var r,e,n,o,i,u;oe||ie();var a=t.length;if(a%4>0)throw new Error("Invalid string. Length must be a multiple of 4");i="="===t[a-2]?2:"="===t[a-1]?1:0,u=new ne(3*a/4-i),n=i>0?a-4:a;var f=0;for(r=0,e=0;r>16&255,u[f++]=o>>8&255,u[f++]=255&o;return 2===i?(o=ee[t.charCodeAt(r)]<<2|ee[t.charCodeAt(r+1)]>>4,u[f++]=255&o):1===i&&(o=ee[t.charCodeAt(r)]<<10|ee[t.charCodeAt(r+1)]<<4|ee[t.charCodeAt(r+2)]>>2,u[f++]=o>>8&255,u[f++]=255&o),u}(function(t){if((t=function(t){if(t.trim)return t.trim();return t.replace(/^\s+|\s+$/g,"")}(t).replace($e,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function He(t,r,e,n){for(var o=0;o=r.length||o>=t.length);++o)r[o+e]=t[o];return o}function We(t){return null!=t&&(!!t._isBuffer||Ze(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&Ze(t.slice(0,0))}(t))}function Ze(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}var Ke=function(t,r){if(r instanceof Error){var e={};return Object.getOwnPropertyNames(r).forEach((function(t){e[t]=r[t]})),e}return r};var Xe=function(t,r){try{var e=t.headers.accept.split(",");return r?e.filter((function(t){return t===r})):e}catch(t){return[]}},tn=function(t,r){return!!Xe(t,r).length},rn=function(t,r){return t.path===r.jsonqlPath};exports.VERSION="1.2.4",exports.assign=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return Reflect.apply(Object.assign,Object,t)},exports.buff=function(t,r){return void 0===r&&(r="base64"),We(t)?t:new ge.from(t,r)},exports.cacheBurst=Yr,exports.cacheBurstUrl=function(t){return Cr(t,Yr())},exports.chainFns=function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];return function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];return r.reduce((function(t,r){return Reflect.apply(r,null,Q(t))}),Reflect.apply(t,null,e))}},exports.chainPromises=function(t,r){return void 0===r&&(r=!1),t.reduce((function(t,e){return t.then((function(t){return e.then((function(e){return!1===r?t.concat([e]):xr(t,e)}))}))}),Promise.resolve(!1===r?[]:j(r)?r:{}))},exports.createAcknowledgeMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("acknowledge_reply",t,r,e)},exports.createEvt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return t.join("_")},exports.createMutation=Jr,exports.createMutationStr=function(t,r,e,n){return void 0===e&&(e={}),void 0===n&&(n=!1),JSON.stringify(Jr(t,r,e,n))},exports.createQuery=qr,exports.createQueryStr=function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(qr(t,r,e))},exports.createReplyMsg=function(t,r,e){return void 0===e&&(e=[]),Xr("emit_reply",t,r,e)},exports.createWsReply=Xr,exports.dasherize=Ir,exports.extractArgsFromPayload=function(t,r){switch(r){case"query":return t.args;case"mutation":return[t.payload,t.condition];default:throw new Ur("Unknown "+r+" to extract argument from!")}},exports.extractParamsFromContract=function(t,r,e){try{var n=t[r][e];if(!n)throw new Tr(e,r);return n}catch(t){throw new Tr(e,t)}},exports.extractSocketPart=Br,exports.extractWsPayload=function(t,r){void 0===r&&(r=Z);try{var e,n=W(t);if(!1!==(e=te(n)))return r("TS",n.TS),{data:W(e.__data__),resolverName:e.__event__,type:e.__reply__};throw new Ur("payload can not decoded",t)}catch(t){return r("error",t)}},exports.findFromContract=function(t,e,n){return!!(n[t]&&n[t][e]&&n[t][e].file&&r.existsSync(n[t][e].file))&&n[t][e].file},exports.formatPayload=zr,exports.freeze=function(t){return Object.freeze(t)},exports.getCallMethod=function(t){switch(!0){case t===Rr[0]:return"query";case t===Rr[1]:return"mutation";default:return!1}},exports.getConfigValue=function(t,r){return r&&j(r)&&t in r?r[t]:void 0},exports.getDocLen=function(t){return ge.byteLength(t,"utf8")},exports.getMutationFromArgs=Qr,exports.getMutationFromPayload=function(t){var r=Gr(t,Qr);if(!1!==r)return r;throw new Sr("[getMutationArgs] Payload is malformed!",t)},exports.getNamespace=Wr,exports.getNamespaceInOrder=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e},exports.getNspInfoByConfig=function(t){var r=t.contract,e=t.enableAuth,n=Wr(t),o=e?Hr(r):function(t,r){var e,n={};for(var o in t){var i=t[o];n[o]=i}return{size:1,nspGroup:(e={},e[r]=n,e),publicNamespace:r}}(r.socket,n[0]);return Object.assign(o,{namespaces:n})},exports.getPathToFn=function(t,n,o){var i=o.resolverDir,u=Ir(t),a=[];o.contract&&o.contract[n]&&o.contract[n].path&&a.push(o.contract[n].path),a.push(e.join(i,n,u,[Or,Pr].join("."))),a.push(e.join(i,n,[u,Pr].join(".")));for(var f=a.length,s=0;s { */ export const assign = (...args) => Reflect.apply(Object.assign, Object, args) - -// generic placeholder function +/** + * generic placeholder function + * @return {boolean} false + */ export const nil = () => false + +/** + * generic turn config into immutatble + */ +export const freeze = config => Object.freeze(config) \ No newline at end of file diff --git a/packages/utils/tests/construct.test.js b/packages/utils/tests/construct.test.js index e7752699..de3b88ee 100644 --- a/packages/utils/tests/construct.test.js +++ b/packages/utils/tests/construct.test.js @@ -1,6 +1,6 @@ // this is ported back from jsonql-params-validator const test = require('ava') -const { isContract, isObjectHasKey, assign } = require('../main') +const { isContract, isObjectHasKey, assign, freeze } = require('../main') const debug = require('debug')('jsonql-utils:construct') test("It should able to check if an object is contract or not", t => { @@ -42,3 +42,24 @@ test(`Testing the assign method`, t => { t.is(result['c'], 3) }) + + +test(`Testing the freeze method`, t => { + + let obj = {name: 'Joel', id: 1} + + obj = freeze(obj) + + const check = Object.isFrozen(obj) + + t.true(check, 'isFreeze') + + obj.name = 'Jack' + + t.is(obj.name, 'Joel', 'Can not change the property') + + obj = freeze(obj) + + debug(`freeze it again make no different`, obj) + +}) \ No newline at end of file diff --git a/packages/ws-client-core/index.js b/packages/ws-client-core/index.js index 06537534..9ad6ebd7 100644 --- a/packages/ws-client-core/index.js +++ b/packages/ws-client-core/index.js @@ -30,6 +30,7 @@ import { createInitPing, extractPingResult, createIntercomPayload, + extractSrvPayload, helloWorld } from './src/callers' // The onion skin cooker @@ -67,5 +68,6 @@ export { createInitPing, extractPingResult, createIntercomPayload, + extractSrvPayload, helloWorld } diff --git a/packages/ws-client-core/src/callers/hello.js b/packages/ws-client-core/src/callers/hello.js index b7e90ce4..e636c31f 100644 --- a/packages/ws-client-core/src/callers/hello.js +++ b/packages/ws-client-core/src/callers/hello.js @@ -9,3 +9,13 @@ import { createQueryStr } from 'jsonql-utils/module' export function helloWorld(deliverFn) { deliverFn(createQueryStr(HELLO_FN, [])) } + + +/** + * This is the capture the helloWorld return method, after passing through the extractWsPayload + * @param {object} data the extracted data from payload + * @return {*} the data part + */ +export function getHelloMsg(data) { + // @TODO +} \ No newline at end of file diff --git a/packages/ws-client-core/src/callers/index.js b/packages/ws-client-core/src/callers/index.js index 6675b923..526e05b9 100644 --- a/packages/ws-client-core/src/callers/index.js +++ b/packages/ws-client-core/src/callers/index.js @@ -7,7 +7,8 @@ import { import { createInitPing, extractPingResult, - createIntercomPayload + createIntercomPayload, + extractSrvPayload } from './intercom-methods' import { callersGenerator } from './callers-generator' @@ -17,5 +18,6 @@ export { createInitPing, extractPingResult, createIntercomPayload, + extractSrvPayload, callersGenerator } diff --git a/packages/ws-client-core/src/callers/intercom-methods.js b/packages/ws-client-core/src/callers/intercom-methods.js index 58258430..2c56be9d 100644 --- a/packages/ws-client-core/src/callers/intercom-methods.js +++ b/packages/ws-client-core/src/callers/intercom-methods.js @@ -22,6 +22,19 @@ import { } from 'jsonql-errors' const CSRF_HEADER_NOT_EXIST_ERR = 'CSRF header is not in the received payload' +/** + * Util method + * @param {string} payload return from server + * @return {object} the useful bit + */ +function extractSrvPayload(payload) { + let json = toJson(payload) + if (json && json.data) { + return extractWsPayload(json.data) + } + throw new JsonqlError('extractSrvPayload', json) +} + /** * call the server to get a csrf token * @return {string} formatted payload to send to the server @@ -37,9 +50,8 @@ function createInitPing() { * @return {object} the csrf payload */ function extractPingResult(payload) { - const json = toJson(payload) - const result = extractWsPayload(json) - if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) { + const result = extractSrvPayload(payload) + if (result && result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) { return { [HEADERS_KEY]: result[DATA_KEY] } @@ -63,6 +75,7 @@ function createIntercomPayload(type, ...args) { export { + extractSrvPayload, createInitPing, extractPingResult, createIntercomPayload diff --git a/packages/ws-client-core/tests/experiment.test.js b/packages/ws-client-core/tests/experiment.test.js index a6ae8c81..f166db70 100644 --- a/packages/ws-client-core/tests/experiment.test.js +++ b/packages/ws-client-core/tests/experiment.test.js @@ -12,6 +12,9 @@ const localDebug = debug('jsonql-ws-client:test:evt') const { chainPromises } = require('jsonql-utils') const { basicClient, fullClient } = require('../../ws-server/client') +const { helloWorld } = require('../src/callers/hello') +const { extractSrvPayload } = require('../index') + const wsServer = require('./fixtures/server-setup') const createToken = require('./fixtures/token') @@ -72,7 +75,18 @@ test.cb(`Test the chainPromises to create client`, t => { }) test.cb.only(`Testing the fullClient with csrf`, t => { - t.plan(2) + t.plan(4) + const evt = t.context.evt + let ctn = 0 + evt.$on('count', i => { + ctn += i + if (ctn > 3) { + t.end() + } + return ctn + }) + + const plus = () => evt.$trigger('count', 1) chainPromises([ fullClient([baseUrl, namespaces[1]].join('/'), t.context.token), @@ -87,15 +101,37 @@ test.cb.only(`Testing the fullClient with csrf`, t => { const c1 = clients.public const c2 = clients.private + const d1 = p => c1.send(p) + const d2 = p => c2.send(p) + + c1.onopen = function() { + helloWorld(d1) + plus() t.pass() } c2.onopen = function() { + helloWorld(d2) + plus() t.pass() - t.end() } + c1.onmessage = function(payload) { + localDebug('c1 payload', extractSrvPayload(payload)) + + t.pass() + plus() + + } + + c2.onmessage = function(payload) { + localDebug(`c2 payload`, extractSrvPayload(payload)) + t.pass() + + plus() + + } }) }) -- Gitee From 0c0b6e26008a76fceb40812088120d593e1bd361 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 12:49:09 +0800 Subject: [PATCH 43/66] jsonql-ws-server-core 0.7.10 --- packages/ws-server-core/README.md | 4 ++-- packages/ws-server-core/package.json | 2 +- packages/ws-server-core/src/handles/get-socket-handler.js | 2 +- packages/ws-server/src/intercom-methods.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/ws-server-core/README.md b/packages/ws-server-core/README.md index 8e61f0ba..8d206b3d 100644 --- a/packages/ws-server-core/README.md +++ b/packages/ws-server-core/README.md @@ -36,10 +36,10 @@ This is for our own reference use **ONLY**: ## TODO (toward V.1 release) - origin / ip checking -- CSRF (TBC) +- ~~CSRF~~ - TS check - standalone mode features -- Intercom event handling +- ~~Intercom event handling~~ --- diff --git a/packages/ws-server-core/package.json b/packages/ws-server-core/package.json index 8b43f936..f2adfd57 100644 --- a/packages/ws-server-core/package.json +++ b/packages/ws-server-core/package.json @@ -36,7 +36,7 @@ "jsonql-jwt": "^1.3.10", "jsonql-params-validator": "^1.6.1", "jsonql-resolver": "^1.1.3", - "jsonql-utils": "^1.2.3", + "jsonql-utils": "^1.2.4", "lodash": "^4.17.15", "nanoid": "^2.1.11", "node-cache": "^5.1.0" diff --git a/packages/ws-server-core/src/handles/get-socket-handler.js b/packages/ws-server-core/src/handles/get-socket-handler.js index 96d0445b..3f487305 100644 --- a/packages/ws-server-core/src/handles/get-socket-handler.js +++ b/packages/ws-server-core/src/handles/get-socket-handler.js @@ -54,7 +54,7 @@ function getSocketHandler(config, ws, deliverFn, req, connectedNamespace, payloa debug('getSocketHandler:intercom') // We don't need to send anything back // @TBC do we need the config return handleInterCom(config, ws, deliverFn, req, connectedNamespace, args, userdata) - case resolverName === HELLO_FN: + case resolverName === HELLO_FN: // basically we hijack it here and no need to care about the contract setup return handleHello(deliverFn, connectedNamespace, userdata) default: const contractParam = matchResolverByNamespace(resolverName, connectedNamespace, nspGroup) diff --git a/packages/ws-server/src/intercom-methods.js b/packages/ws-server/src/intercom-methods.js index 96cc517f..e2650b3f 100644 --- a/packages/ws-server/src/intercom-methods.js +++ b/packages/ws-server/src/intercom-methods.js @@ -33,7 +33,7 @@ function createInitPing() { /** * Take the raw on.message result back then decoded it - * @param {*} payload the raw result = require( server + * @param {*} payload the raw result from server? * @return {object} the csrf payload */ function extractPingResult(payload) { -- Gitee From 685fc34fab89e973eadbff8a9711b392e2ca1887 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 12:50:48 +0800 Subject: [PATCH 44/66] update deps --- packages/ws-server/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json index 34d13f96..fbcfafba 100755 --- a/packages/ws-server/package.json +++ b/packages/ws-server/package.json @@ -34,8 +34,8 @@ "colors": "^1.4.0", "debug": "^4.1.1", "jsonql-constants": "^2.0.4", - "jsonql-utils": "^1.2.3", - "jsonql-ws-server-core": "^0.7.9", + "jsonql-utils": "^1.2.4", + "jsonql-ws-server-core": "^0.7.10", "ws": "^7.2.3" }, "devDependencies": { -- Gitee From aa0a3e98b55c1076e137d8313a4bdae7c9c6d8e5 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 12:51:41 +0800 Subject: [PATCH 45/66] update the latest server-core and test pass --- packages/ws-server/src/modules.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ws-server/src/modules.js b/packages/ws-server/src/modules.js index 193e7837..aaf568ea 100644 --- a/packages/ws-server/src/modules.js +++ b/packages/ws-server/src/modules.js @@ -19,8 +19,8 @@ const { SOCKET_STATE_KEY, getSocketHandler -} = require('../../ws-server-core') -// require('jsonql-ws-server-core') +} = require('jsonql-ws-server-core') +// require('../../ws-server-core') module.exports = { WebSocket, -- Gitee From e031cc8828ff0bb2d30e2fc505fbe657cecf7bca Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 13:12:31 +0800 Subject: [PATCH 46/66] fixture out the different between the server / client extra data different --- .../ws-client-core/src/callers/intercom-methods.js | 10 ++++++++-- packages/ws-client-core/tests/experiment.test.js | 4 ++-- packages/ws-client-core/tests/init.test.js | 6 ++---- packages/ws-server/package.json | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/ws-client-core/src/callers/intercom-methods.js b/packages/ws-client-core/src/callers/intercom-methods.js index 2c56be9d..a8157bfb 100644 --- a/packages/ws-client-core/src/callers/intercom-methods.js +++ b/packages/ws-client-core/src/callers/intercom-methods.js @@ -29,9 +29,12 @@ const CSRF_HEADER_NOT_EXIST_ERR = 'CSRF header is not in the received payload' */ function extractSrvPayload(payload) { let json = toJson(payload) - if (json && json.data) { - return extractWsPayload(json.data) + + if (json && typeof json === 'object') { + // note this method expect the json.data inside + return extractWsPayload(json) } + throw new JsonqlError('extractSrvPayload', json) } @@ -41,6 +44,7 @@ function extractSrvPayload(payload) { */ function createInitPing() { const ts = timestamp() + return createQueryStr(INTERCOM_RESOLVER_NAME, [SOCKET_PING_EVENT_NAME, ts]) } @@ -51,11 +55,13 @@ function createInitPing() { */ function extractPingResult(payload) { const result = extractSrvPayload(payload) + if (result && result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) { return { [HEADERS_KEY]: result[DATA_KEY] } } + throw new JsonqlError('extractPingResult', CSRF_HEADER_NOT_EXIST_ERR) } diff --git a/packages/ws-client-core/tests/experiment.test.js b/packages/ws-client-core/tests/experiment.test.js index f166db70..d5cc573d 100644 --- a/packages/ws-client-core/tests/experiment.test.js +++ b/packages/ws-client-core/tests/experiment.test.js @@ -118,7 +118,7 @@ test.cb.only(`Testing the fullClient with csrf`, t => { } c1.onmessage = function(payload) { - localDebug('c1 payload', extractSrvPayload(payload)) + localDebug('c1 payload', extractSrvPayload(payload.data)) t.pass() plus() @@ -126,7 +126,7 @@ test.cb.only(`Testing the fullClient with csrf`, t => { } c2.onmessage = function(payload) { - localDebug(`c2 payload`, extractSrvPayload(payload)) + localDebug(`c2 payload`, extractSrvPayload(payload.data)) t.pass() plus() diff --git a/packages/ws-client-core/tests/init.test.js b/packages/ws-client-core/tests/init.test.js index 6de14504..266a6c70 100644 --- a/packages/ws-client-core/tests/init.test.js +++ b/packages/ws-client-core/tests/init.test.js @@ -8,7 +8,7 @@ const { const debug = require('debug')('jsonql-ws-server:test:ws') const port = 8899 -const { createInitPing, extractPingResult } = require('../src/listener/intercom-methods') +const { createInitPing, extractPingResult } = require('../src/callers/intercom-methods') test.before(async t => { const { app } = await wsServer() @@ -29,14 +29,12 @@ test.cb(`Testing the init ping call`, t => { client.on('open', () => { const payload = createInitPing() - debug(payload) - client.send(payload) }) client.on('message', data => { - + // that prove that on the server side and client side the data is different structure debug('raw data', typeof data, data) const header = extractPingResult(data) diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json index fbcfafba..5baad1e4 100755 --- a/packages/ws-server/package.json +++ b/packages/ws-server/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-ws-server", - "version": "1.7.6", + "version": "1.7.7", "description": "Setup WebSocket server for the jsonql to run on the same host, automatic generate public / private channel using contract", "main": "index.js", "files": [ -- Gitee From 611ba834ef239f8dffe0a107dfcc5ed4fa4942ca Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 13:24:58 +0800 Subject: [PATCH 47/66] jsonql-ws-server to 1.7.7 --- .../ws-server-core/src/handles/get-socket-handler.js | 6 ++++-- packages/ws-server-core/src/options/constants.js | 5 ++++- packages/ws-server-core/src/share/resolver-methods.js | 5 ++++- .../src/core/security/create-verify-client.js | 11 +++++++---- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/ws-server-core/src/handles/get-socket-handler.js b/packages/ws-server-core/src/handles/get-socket-handler.js index 3f487305..5293cc13 100644 --- a/packages/ws-server-core/src/handles/get-socket-handler.js +++ b/packages/ws-server-core/src/handles/get-socket-handler.js @@ -51,18 +51,20 @@ function getSocketHandler(config, ws, deliverFn, req, connectedNamespace, payloa // it might be the special internal event? switch (true) { case resolverName === INTERCOM_RESOLVER_NAME: - debug('getSocketHandler:intercom') + // debug('getSocketHandler:intercom') // We don't need to send anything back // @TBC do we need the config return handleInterCom(config, ws, deliverFn, req, connectedNamespace, args, userdata) case resolverName === HELLO_FN: // basically we hijack it here and no need to care about the contract setup return handleHello(deliverFn, connectedNamespace, userdata) default: const contractParam = matchResolverByNamespace(resolverName, connectedNamespace, nspGroup) + debug('getSocketHandler:default', contractParam) + if (contractParam === false) { // just return an error return handleUnknownPayload(deliverFn, resolverName, args) } - debug('getSocketHandler:default', contractParam) + handleNspResolvers(deliverFn, ws, resolverName, args, contractParam.params, config, userdata) } diff --git a/packages/ws-server-core/src/options/constants.js b/packages/ws-server-core/src/options/constants.js index 0044d477..bcbec1f6 100644 --- a/packages/ws-server-core/src/options/constants.js +++ b/packages/ws-server-core/src/options/constants.js @@ -26,6 +26,8 @@ const CONTRACT_NOT_FOUND_ERR = `No contract presented!` const NO_TOKEN_ERR_MSG = `No token!` +const HEADER_CHECK_FAIL_MSG = 'Header check failed' + module.exports = { SOCKET_IO, WS, @@ -37,6 +39,7 @@ module.exports = { CONTRACT_NOT_FOUND_ERR, SOCKET_AUTH_DIR, SOCKET_STATE_KEY, - + + HEADER_CHECK_FAIL_MSG, NO_TOKEN_ERR_MSG } diff --git a/packages/ws-server-core/src/share/resolver-methods.js b/packages/ws-server-core/src/share/resolver-methods.js index b3907dc3..3109b8b3 100644 --- a/packages/ws-server-core/src/share/resolver-methods.js +++ b/packages/ws-server-core/src/share/resolver-methods.js @@ -53,9 +53,11 @@ function handleResult(deliverFn, resolverName, result, type) { * @return {void} */ function handleError(deliverFn, resolverName, err) { - debug('--> CATCH RESOLVER ERROR <--') const payload = createWsReply(ERROR_KEY, resolverName, packError(err)) + + debug('--> CATCH RESOLVER ERROR <--') debug(ERROR_KEY, resolverName, payload) + deliverFn(payload) } @@ -68,6 +70,7 @@ function handleError(deliverFn, resolverName, err) { * @return {void} */ function deliverMsg(deliverFn, resolverName, result, type = ACKNOWLEDGE_REPLY_TYPE) { + return Promise .resolve(result) .then(result => handleResult(deliverFn, resolverName, result, type)) diff --git a/packages/ws-server/src/core/security/create-verify-client.js b/packages/ws-server/src/core/security/create-verify-client.js index 758b65d0..74a4c587 100644 --- a/packages/ws-server/src/core/security/create-verify-client.js +++ b/packages/ws-server/src/core/security/create-verify-client.js @@ -96,20 +96,23 @@ function createVerifyClient(namespace, opts, jwtOptions = {}, cb = localCb) { return function verifyClient(info, done) { const { req } = info if (!checkHeaders(opts, req)) { + // @TODO replace with share constants from ws-server-core cb('Header check failed') return done(false) } debug('nspInfo', nspInfo) - - debug('what the fuck is happening here?', namespace, publicNamespace) - + // debug('what the fuck is happening here?', namespace, publicNamespace) // also need to check if this is the private namespace as well! if (!enableAuth || namespace === publicNamespace) { // cb(`public namespace no need to check`, namespace, publicNamespace) return done(true) // job done here } + // @TODO here we need to take the interceptor.validate method that created by + // develop to run their own checks + + // auth features const uri = req.url const token = getTokenFromQuery(uri) @@ -132,7 +135,7 @@ function createVerifyClient(namespace, opts, jwtOptions = {}, cb = localCb) { done(false) } } - // @BUG error then what todo? + // @TODO replace with share constants from ws-server-core cb('no token!') done(false) } -- Gitee From af6c48e5f8b487e77dd7325cb62231027651059e Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 13:29:35 +0800 Subject: [PATCH 48/66] update the setup and all test passed --- packages/ws-client-core/package.json | 4 ++-- packages/ws-client-core/tests/experiment.test.js | 2 +- packages/ws-client-core/tests/fixtures/server-setup.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json index c3e69092..5c873d20 100644 --- a/packages/ws-client-core/package.json +++ b/packages/ws-client-core/package.json @@ -59,7 +59,7 @@ "jsonql-constants": "^2.0.4", "jsonql-errors": "^1.2.1", "jsonql-params-validator": "^1.6.1", - "jsonql-utils": "^1.2.2" + "jsonql-utils": "^1.2.4" }, "devDependencies": { "ava": "^3.5.0", @@ -67,7 +67,7 @@ "fs-extra": "^8.1.0", "jsonql-contract": "^1.8.10", "jsonql-jwt": "^1.3.10", - "jsonql-ws-server": "^1.7.6", + "jsonql-ws-server": "^1.7.7", "kefir": "^3.8.6", "ws": "^7.2.3" }, diff --git a/packages/ws-client-core/tests/experiment.test.js b/packages/ws-client-core/tests/experiment.test.js index d5cc573d..068c7749 100644 --- a/packages/ws-client-core/tests/experiment.test.js +++ b/packages/ws-client-core/tests/experiment.test.js @@ -11,7 +11,7 @@ const localDebug = debug('jsonql-ws-client:test:evt') const { chainPromises } = require('jsonql-utils') -const { basicClient, fullClient } = require('../../ws-server/client') +const { basicClient, fullClient } = require('jsonql-ws-server/client') // require('../../ws-server/client') const { helloWorld } = require('../src/callers/hello') const { extractSrvPayload } = require('../index') diff --git a/packages/ws-client-core/tests/fixtures/server-setup.js b/packages/ws-client-core/tests/fixtures/server-setup.js index ef2cf2c3..0f27ea07 100644 --- a/packages/ws-client-core/tests/fixtures/server-setup.js +++ b/packages/ws-client-core/tests/fixtures/server-setup.js @@ -6,8 +6,8 @@ const { join } = require('path') const resolverDir = join(__dirname, 'resolvers') - -const { jsonqlWsServer } = require('../../../ws-server') //require('jsonql-ws-server') +// require('../../../ws-server') +const { jsonqlWsServer } = require('jsonql-ws-server') // start const server = http.createServer(function(req, res) { -- Gitee From 00b36937bda56f09b346b1c591055d1678050a4a Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 14:04:15 +0800 Subject: [PATCH 49/66] update the connect method to use the CSRF option again --- .../init-websocket-client.js | 53 +++++++++---------- 1 file changed, 25 insertions(+), 28 deletions(-) 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 cc523b05..355c7b34 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 @@ -27,18 +27,13 @@ function initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) { ws.onmessage = function onMessageCallback(payload) { try { const header = extractPingResult(payload.data) - // the csrf cause all kinds of problem so we abandoned it for now - return resolver(ws) - /* - // terminate the client - ws.terminate() - // return the new one with csrf header - // @BUG too quick and kill the socket? - setTimeout(() => { - const newWs = new WebSocket(url, Object.assign(wsOptions, header)) - resolver(newWs) + // @NOTE the break down test in ws-client-core show no problems + // the problem was cause by malform nspInfo that time? + setTimeout(() => { // delay or not show no different but just on the safe side + ws.terminate() }, 50) - */ + const newWs = new WebSocket(url, Object.assign(wsOptions, header)) + resolver(newWs) } catch(e) { rejecter(e) } @@ -49,6 +44,23 @@ function initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) { } } +/** + * less duplicated code the better + * @param {string} url formatted url + * @param {object} options or not + * @return {promise} resolve the actual verified client + */ +function asyncConnect(url, options) { + + return new Promise((resolver, rejecter) => { + + const unconfirmClient = new WebSocket(url, options) + + initPingAction(unconfirmClient, WebSocket, url, resolver, rejecter, options) + }) +} + + /** * The bug was in the wsOptions where ws don't need it but socket.io do * therefore the object was pass as second parameter! @@ -67,17 +79,9 @@ function initWebSocketClient(WebSocket, auth, log) { */ return function createWsClient(url, wsOptions = {}) { const _url = fixWss(url) - log(`nspClient: \n${_url}\n`, wsOptions) - return new Promise((resolver, rejecter) => { - - const unconfirmClient = new WebSocket(_url, wsOptions) - - resolver(unconfirmClient) - - // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) - }) + return asyncConnect(_url, wsOptions) } } @@ -92,16 +96,9 @@ function initWebSocketClient(WebSocket, auth, log) { const ws_url = fixWss(url) // console.log('what happen here?', url, ws_url, token) const _url = token && typeof token === 'string' ? `${ws_url}?${TOKEN_PARAM_NAME}=${token}` : ws_url - log(`nspAuthClient: \n${_url}\n`, wsOptions) - return new Promise((resolver, rejecter) => { - const unconfirmClient = new WebSocket(_url, wsOptions) - - resolver(unconfirmClient) - - // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) - }) + return asyncConnect(_url, wsOptions) } } -- Gitee From 4b64ecc61fcc5e7e0a1658ce5c1f4ba6582147cb Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 15:10:18 +0800 Subject: [PATCH 50/66] Update the clientEventListener interface now its much easier to read --- packages/@jsonql/ws/src/core/create-nsp/create-nsp.js | 10 +++++----- packages/@jsonql/ws/src/core/modules.js | 4 ++-- packages/@jsonql/ws/tests/ws-client-auth-login.test.js | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/@jsonql/ws/src/core/create-nsp/create-nsp.js b/packages/@jsonql/ws/src/core/create-nsp/create-nsp.js index 4992b7cd..8b8feb0f 100644 --- a/packages/@jsonql/ws/src/core/create-nsp/create-nsp.js +++ b/packages/@jsonql/ws/src/core/create-nsp/create-nsp.js @@ -1,7 +1,7 @@ // actually binding the event client to the socket client // from the jsonql-ws-client-core -import { clientEventHandler } from '../modules' +import { clientEventListener } from '../modules' // local import { createNspAction } from './create-nsp-action' import { loginEventHandler } from './login-event-handler' @@ -15,16 +15,16 @@ import { bindSocketEventHandler } from './bind-socket-event-handler' * @return {object} what comes in what goes out */ function createNsp(opts, nspMap, ee) { - // arguments for clientEventHandler - const args = [opts, nspMap, ee, bindSocketEventHandler] // now create the nsps // const { namespaces } = nspMap const { token } = opts return createNspAction(opts, nspMap, token) .then(nsps => { - args.push(nsps) - Reflect.apply(clientEventHandler, null, args) + const listenerFn = clientEventListener(bindSocketEventHandler, nsps) + // now run it + listenerFn(opts, nspMap, ee) + if (opts.enableAuth) { loginEventHandler(opts, nspMap, ee) } diff --git a/packages/@jsonql/ws/src/core/modules.js b/packages/@jsonql/ws/src/core/modules.js index c16472ee..b219424a 100644 --- a/packages/@jsonql/ws/src/core/modules.js +++ b/packages/@jsonql/ws/src/core/modules.js @@ -21,7 +21,7 @@ import { getEventEmitter, EventEmitterClass, - clientEventHandler, + clientEventListener, createCombineClient, createInitPing, @@ -51,7 +51,7 @@ export { getEventEmitter, EventEmitterClass, - clientEventHandler, + clientEventListener, createCombineClient, createInitPing, diff --git a/packages/@jsonql/ws/tests/ws-client-auth-login.test.js b/packages/@jsonql/ws/tests/ws-client-auth-login.test.js index 7d96e955..f2ffedf3 100644 --- a/packages/@jsonql/ws/tests/ws-client-auth-login.test.js +++ b/packages/@jsonql/ws/tests/ws-client-auth-login.test.js @@ -10,6 +10,7 @@ const genToken = require('./fixtures/token') const contractDir = join(__dirname, 'fixtures', 'contract', 'auth') const contract = fsx.readJsonSync(join(contractDir, 'contract.json')) const publicContract = fsx.readJsonSync(join(contractDir, 'public-contract.json')) + const { NOT_LOGIN_ERR_MSG } = require('jsonql-constants') const payload = {name: 'Joel'}; -- Gitee From 9cee98ec96b632a1e8b881eff098973e9e92bec3 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 15:28:01 +0800 Subject: [PATCH 51/66] Fix the basic connect problem --- packages/@jsonql/ws/main.js | 11117 ++++++++-------- packages/@jsonql/ws/main.js.map | 2 +- .../init-websocket-client.js | 7 +- 3 files changed, 5686 insertions(+), 5440 deletions(-) diff --git a/packages/@jsonql/ws/main.js b/packages/@jsonql/ws/main.js index c9578c96..1350edab 100644 --- a/packages/@jsonql/ws/main.js +++ b/packages/@jsonql/ws/main.js @@ -4,41 +4,118 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'defau var WebSocket = _interopDefault(require('ws')); -var global$1 = (typeof global !== "undefined" ? global : - typeof self !== "undefined" ? self : - typeof window !== "undefined" ? window : {}); +/* base.js */ +// the core stuff to id if it's calling with jsonql +var DATA_KEY = 'data'; +var ERROR_KEY = 'error'; +var HEADERS_KEY = 'headers'; -/** Detect free variable `global` from Node.js. */ -var freeGlobal = typeof global$1 == 'object' && global$1 && global$1.Object === Object && global$1; +var JSONQL_PATH = 'jsonql'; -/** Detect free variable `self`. */ -var freeSelf = typeof self == 'object' && self && self.Object === Object && self; +// export const INDEX = 'index' use INDEX_KEY instead +var DEFAULT_TYPE = 'any'; -/** Used as a reference to the global object. */ -var root = freeGlobal || freeSelf || Function('return this')(); +// @TODO remove this is not in use +// export const CLIENT_CONFIG_FILE = '.clients.json' +// export const CONTRACT_CONFIG_FILE = 'jsonql-contract-config.js' +// type of resolvers +var QUERY_NAME = 'query'; +var MUTATION_NAME = 'mutation'; +var SOCKET_NAME = 'socket'; +var QUERY_ARG_NAME = 'args'; +var TIMESTAMP_PARAM_NAME = 'TS'; +// for contract-cli +var KEY_WORD = 'continue'; +var PUBLIC_KEY = 'public'; +var PRIVATE_KEY = 'private'; +var LOGIN_FN_NAME = 'login'; +// export const ISSUER_NAME = LOGIN_NAME // legacy issue need to replace them later +var LOGOUT_FN_NAME = 'logout'; +var DISCONNECT_FN_NAME = 'disconnect'; +var SWITCH_USER_FN_NAME = 'switch-user'; +// headers +var CSRF_HEADER_KEY = 'X-CSRF-Token'; + /* prop.js */ -/** Built-in value references. */ -var Symbol = root.Symbol; +// this is all the key name for the config check map +// all subfix with prop_key -/** - * A specialized version of `_.map` for arrays without support for iteratee - * shorthands. - * - * @private - * @param {Array} [array] The array to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Array} Returns the new mapped array. - */ -function arrayMap(array, iteratee) { - var index = -1, - length = array == null ? 0 : array.length, - result = Array(length); +var TYPE_KEY = 'type'; +var OPTIONAL_KEY = 'optional'; +var ENUM_KEY = 'enumv'; // need to change this because enum is a reserved word +var ARGS_KEY = 'args'; +var CHECKER_KEY = 'checker'; +var ALIAS_KEY = 'alias'; +var ENABLE_AUTH_PROP_KEY = 'enableAuth'; +var LOGIN_FN_NAME_PROP_KEY = 'loginHandlerName'; +var LOGOUT_FN_NAME_PROP_KEY = 'logoutHandlerName'; +var DISCONNECT_FN_NAME_PROP_KEY = 'disconnectHandlerName'; +var SWITCH_USER_FN_NAME_PROP_KEY = 'switchUserHandlerName'; +// type name and Alias +var SOCKET_TYPE_PROP_KEY = 'serverType'; //1.9.1 +var SOCKET_TYPE_CLIENT_ALIAS = 'socketClientType'; // 1.9.0 - while (++index < length) { - result[index] = iteratee(array[index], index, array); - } - return result; -} +var STANDALONE_PROP_KEY = 'standalone'; +var DEBUG_ON_PROP_KEY = 'debugOn'; + +var HOSTNAME_PROP_KEY = 'hostname'; +var NAMESAPCE_PROP_KEY = 'namespace'; + +var WS_OPT_PROP_KEY = 'wsOptions'; + +var CONTRACT_PROP_KEY = 'contract'; +var TOKEN_PROP_KEY = 'token'; + + /* socket.js */ + +// the constants file is gettig too large +// we need to split up and group the related constant in one file +// also it makes the other module easiler to id what they are importing +// use throughout the clients +var SOCKET_PING_EVENT_NAME = '__ping__'; // when init connection do a ping +var LOGIN_EVENT_NAME = '__login__'; +var LOGOUT_EVENT_NAME = '__logout__'; +var DISCONNECT_EVENT_NAME = '__disconnect__'; +// instead of using an event name in place of resolverName in the param +// we use this internal resolverName instead, and in type using the event names +var INTERCOM_RESOLVER_NAME = '__intercom__'; +// for ws servers +var WS_REPLY_TYPE = '__reply__'; +var WS_EVT_NAME = '__event__'; +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_ERROR_FN_NAME = 'onError'; +var ON_READY_FN_NAME = 'onReady'; +var ON_LOGIN_FN_NAME = 'onLogin'; // new @1.8.6 +// the actual method name client.resolverName.send +var SEND_MSG_FN_NAME = 'send'; + +// this is somewhat vague about what is suppose to do +var EMIT_REPLY_TYPE = 'emit_reply'; + + +var NSP_GROUP = 'nspGroup'; +var PUBLIC_NAMESPACE = 'publicNamespace'; +var NOT_LOGIN_ERR_MSG = 'NOT LOGIN'; +var IO_ROUNDTRIP_LOGIN = 'roundtip'; +var IO_HANDSHAKE_LOGIN = 'handshake'; + /* validation.js */ + +// validation related constants + + +var OR_SEPERATOR = '|'; +var STRING_TYPE = 'string'; +var BOOLEAN_TYPE = 'boolean'; +var ARRAY_TYPE = 'array'; +var OBJECT_TYPE = 'object'; + +var NUMBER_TYPE = 'number'; +var ARRAY_TYPE_LFT = 'array.<'; +var ARRAY_TYPE_RGT = '>'; /** * Checks if `value` is classified as an `Array` object. @@ -65,6 +142,22 @@ function arrayMap(array, iteratee) { */ var isArray = Array.isArray; +var global$1 = (typeof global !== "undefined" ? global : + typeof self !== "undefined" ? self : + typeof window !== "undefined" ? window : {}); + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = typeof global$1 == 'object' && global$1 && global$1.Object === Object && global$1; + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = freeGlobal || freeSelf || Function('return this')(); + +/** Built-in value references. */ +var Symbol = root.Symbol; + /** Used for built-in method references. */ var objectProto = Object.prototype; @@ -152,6 +245,23 @@ function baseGetTag(value) { : objectToString(value); } +/** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ +function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; +} + +/** Built-in value references. */ +var getPrototype = overArg(Object.getPrototypeOf, Object); + /** * Checks if `value` is object-like. A value is object-like if it's not `null` * and has a `typeof` result of "object". @@ -180,6 +290,83 @@ function isObjectLike(value) { return value != null && typeof value == 'object'; } +/** `Object#toString` result references. */ +var objectTag = '[object Object]'; + +/** Used for built-in method references. */ +var funcProto = Function.prototype, + objectProto$2 = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty$1 = objectProto$2.hasOwnProperty; + +/** Used to infer the `Object` constructor. */ +var objectCtorString = funcToString.call(Object); + +/** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ +function isPlainObject(value) { + if (!isObjectLike(value) || baseGetTag(value) != objectTag) { + return false; + } + var proto = getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty$1.call(proto, 'constructor') && proto.constructor; + return typeof Ctor == 'function' && Ctor instanceof Ctor && + funcToString.call(Ctor) == objectCtorString; +} + +/** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ +function arrayMap(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; +} + /** `Object#toString` result references. */ var symbolTag = '[object Symbol]'; @@ -539,915 +726,763 @@ function trim(string, chars, guard) { return castSlice(strSymbols, start, end).join(''); } +// bunch of generic helpers + /** - * Check several parameter that there is something in the param - * @param {*} param input - * @return {boolean} + * DIY in Array + * @param {array} arr to check from + * @param {*} value to check against + * @return {boolean} true on found */ - var isNotEmpty = function (a) { - if (isArray(a)) { - return true; - } - return a !== undefined && a !== null && trim(a) !== '' -}; +var inArray = function (arr, value) { return !!arr.filter(function (a) { return a === value; }).length; }; -/** `Object#toString` result references. */ -var numberTag = '[object Number]'; +// quick and dirty to turn non array to array +var toArray = function (arg) { return isArray(arg) ? arg : [arg]; }; /** - * Checks if `value` is classified as a `Number` primitive or object. - * - * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are - * classified as numbers, use the `_.isFinite` method. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a number, else `false`. - * @example - * - * _.isNumber(3); - * // => true - * - * _.isNumber(Number.MIN_VALUE); - * // => true - * - * _.isNumber(Infinity); - * // => true + * parse string to json or just return the original value if error happened + * @param {*} n input + * @param {boolean} [t=true] or throw + * @return {*} json object on success + */ +var parseJson = function(n, t) { + if ( t === void 0 ) t=true; + + try { + return JSON.parse(n) + } catch(e) { + if (t) { + return n + } + throw new Error(e) + } +}; + +/** + * @param {object} obj for search + * @param {string} key target + * @return {boolean} true on success + */ +var isObjectHasKey = function(obj, key) { + try { + var keys = Object.keys(obj); + return inArray(keys, key) + } catch(e) { + // @BUG when the obj is not an OBJECT we got some weird output + return false + } +}; + +/** + * create a event name + * @param {string[]} args + * @return {string} event name for use + */ +var createEvt = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return args.join('_'); +}; + +/** + * small util to make sure the return value is valid JSON object + * @param {*} n input + * @return {object} correct JSON object + */ +var toJson = function (n) { + if (typeof n === 'string') { + return parseJson(n) + } + return parseJson(JSON.stringify(n)) +}; + +/** + * Simple check if the prop is function + * @param {*} prop input + * @return {boolean} true on success + */ +var isFunc = function (prop) { + if (typeof prop === 'function') { + return true; + } + console.error(("Expect to be Function type! Got " + (typeof prop))); +}; + +/** + * generic placeholder function + * @return {boolean} false + */ +var nil = function () { return false; }; + +/** + * using just the map reduce to chain multiple functions together + * @param {function} mainFn the init function + * @param {array} moreFns as many as you want to take the last value and return a new one + * @return {function} accept value for the mainFn + */ +var chainFns = function (mainFn) { + var moreFns = [], len = arguments.length - 1; + while ( len-- > 0 ) moreFns[ len ] = arguments[ len + 1 ]; + + return ( + function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return ( + moreFns.reduce(function (value, nextFn) { return ( + // change here to check if the return value is array then we spread it + Reflect.apply(nextFn, null, toArray(value)) + ); }, Reflect.apply(mainFn, null, args)) + ); + } +); +}; + +/** + * Removes all key-value entries from the list cache. * - * _.isNumber('3'); - * // => false + * @private + * @name clear + * @memberOf ListCache */ -function isNumber(value) { - return typeof value == 'number' || - (isObjectLike(value) && baseGetTag(value) == numberTag); +function listCacheClear() { + this.__data__ = []; + this.size = 0; } /** - * Checks if `value` is `NaN`. - * - * **Note:** This method is based on - * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as - * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for - * `undefined` and other non-number values. + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. * * @static * @memberOf _ - * @since 0.1.0 + * @since 4.0.0 * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * - * _.isNaN(NaN); - * // => true + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; * - * _.isNaN(new Number(NaN)); + * _.eq(object, object); * // => true * - * isNaN(undefined); + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); * // => true * - * _.isNaN(undefined); + * _.eq('a', Object('a')); * // => false + * + * _.eq(NaN, NaN); + * // => true */ -function isNaN(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. - return isNumber(value) && value != +value; +function eq(value, other) { + return value === other || (value !== value && other !== other); } -/** `Object#toString` result references. */ -var stringTag = '[object String]'; - /** - * Checks if `value` is classified as a `String` primitive or object. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a string, else `false`. - * @example - * - * _.isString('abc'); - * // => true + * Gets the index at which the `key` is found in `array` of key-value pairs. * - * _.isString(1); - * // => false + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. */ -function isString(value) { - return typeof value == 'string' || - (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); +function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; } -// validator numbers -/** - * @2015-05-04 found a problem if the value is a number like string - * it will pass, so add a chck if it's string before we pass to next - * @param {number} value expected value - * @return {boolean} true if OK - */ -var checkIsNumber = function(value) { - return isString(value) ? false : !isNaN( parseFloat(value) ) -}; +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/** Built-in value references. */ +var splice = arrayProto.splice; -// validate string type /** - * @param {string} value expected value - * @return {boolean} true if OK + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ -var checkIsString = function(value) { - return (trim(value) !== '') ? isString(value) : false -}; +function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); -// check for boolean + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; +} /** - * @param {boolean} value expected - * @return {boolean} true if OK + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. */ -var checkIsBoolean = function(value) { - return value !== null && value !== undefined && typeof value === 'boolean' -}; +function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); -// validate any thing only check if there is something + return index < 0 ? undefined : data[index][1]; +} /** - * @param {*} value the value - * @param {boolean} [checkNull=true] strict check if there is null value - * @return {boolean} true is OK + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ -var checkIsAny = function(value, checkNull) { - if ( checkNull === void 0 ) checkNull = true; - - if (value !== undefined && value !== '' && trim(value) !== '') { - if (checkNull === false || (checkNull === true && value !== null)) { - return true; - } - } - return false; -}; - -/* base.js */ -// the core stuff to id if it's calling with jsonql -var DATA_KEY = 'data'; -var ERROR_KEY = 'error'; - -var JSONQL_PATH = 'jsonql'; - -// export const INDEX = 'index' use INDEX_KEY instead -var DEFAULT_TYPE = 'any'; - -// @TODO remove this is not in use -// export const CLIENT_CONFIG_FILE = '.clients.json' -// export const CONTRACT_CONFIG_FILE = 'jsonql-contract-config.js' -// type of resolvers -var QUERY_NAME = 'query'; -var MUTATION_NAME = 'mutation'; -var SOCKET_NAME = 'socket'; -var QUERY_ARG_NAME = 'args'; -var TIMESTAMP_PARAM_NAME = 'TS'; -// for contract-cli -var KEY_WORD = 'continue'; -var PUBLIC_KEY = 'public'; -var PRIVATE_KEY = 'private'; -var LOGIN_FN_NAME = 'login'; -// export const ISSUER_NAME = LOGIN_NAME // legacy issue need to replace them later -var LOGOUT_FN_NAME = 'logout'; -var DISCONNECT_FN_NAME = 'disconnect'; -var SWITCH_USER_FN_NAME = 'switch-user'; - /* prop.js */ - -// this is all the key name for the config check map -// all subfix with prop_key - -var TYPE_KEY = 'type'; -var OPTIONAL_KEY = 'optional'; -var ENUM_KEY = 'enumv'; // need to change this because enum is a reserved word -var ARGS_KEY = 'args'; -var CHECKER_KEY = 'checker'; -var ALIAS_KEY = 'alias'; -var ENABLE_AUTH_PROP_KEY = 'enableAuth'; -var LOGIN_FN_NAME_PROP_KEY = 'loginHandlerName'; -var LOGOUT_FN_NAME_PROP_KEY = 'logoutHandlerName'; -var DISCONNECT_FN_NAME_PROP_KEY = 'disconnectHandlerName'; -var SWITCH_USER_FN_NAME_PROP_KEY = 'switchUserHandlerName'; -// type name and Alias -var SOCKET_TYPE_PROP_KEY = 'serverType'; //1.9.1 -var SOCKET_TYPE_CLIENT_ALIAS = 'socketClientType'; // 1.9.0 - -var STANDALONE_PROP_KEY = 'standalone'; -var DEBUG_ON_PROP_KEY = 'debugOn'; - -var HOSTNAME_PROP_KEY = 'hostname'; -var NAMESAPCE_PROP_KEY = 'namespace'; - -var WS_OPT_PROP_KEY = 'wsOptions'; - -var CONTRACT_PROP_KEY = 'contract'; -var TOKEN_PROP_KEY = 'token'; -var LOGIN_EVENT_NAME = '__login__'; -var LOGOUT_EVENT_NAME = '__logout__'; -var DISCONNECT_EVENT_NAME = '__disconnect__'; -// instead of using an event name in place of resolverName in the param -// we use this internal resolverName instead, and in type using the event names -var INTERCOM_RESOLVER_NAME = '__intercom__'; - -// 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_ERROR_FN_NAME = 'onError'; -var ON_READY_FN_NAME = 'onReady'; -var ON_LOGIN_FN_NAME = 'onLogin'; // new @1.8.6 -// the actual method name client.resolverName.send -var SEND_MSG_FN_NAME = 'send'; - -// this is somewhat vague about what is suppose to do -var EMIT_REPLY_TYPE = 'emit_reply'; - - -var NSP_GROUP = 'nspGroup'; -var PUBLIC_NAMESPACE = 'publicNamespace'; - -var JS_WS_SOCKET_IO_NAME = 'socket.io'; -var NOT_LOGIN_ERR_MSG = 'NOT LOGIN'; -var IO_ROUNDTRIP_LOGIN = 'roundtip'; -var IO_HANDSHAKE_LOGIN = 'handshake'; - /* validation.js */ - -// validation related constants - - -var OR_SEPERATOR = '|'; -var STRING_TYPE = 'string'; -var BOOLEAN_TYPE = 'boolean'; -var ARRAY_TYPE = 'array'; -var OBJECT_TYPE = 'object'; - -var NUMBER_TYPE = 'number'; -var ARRAY_TYPE_LFT = 'array.<'; -var ARRAY_TYPE_RGT = '>'; - -// Good practice rule - No magic number - -var 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)"; -var PARAMS_NOT_ARRAY_ERR = "params is not an array! Did something gone wrong when you generate the contract.json?"; -var EXCEPTION_CASE_ERR = 'Could not understand your arguments and parameter structure!'; - -// primitive types +function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; +} /** - * this is a wrapper method to call different one based on their type - * @param {string} type to check - * @return {function} a function to handle the type + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. */ -var combineFn = function(type) { - switch (type) { - case NUMBER_TYPE: - return checkIsNumber - case STRING_TYPE: - return checkIsString - case BOOLEAN_TYPE: - return checkIsBoolean - default: - return checkIsAny - } -}; +function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); -// validate array type + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; +} /** - * @param {array} value expected - * @param {string} [type=''] pass the type if we encounter array. then we need to check the value as well - * @return {boolean} true if OK + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. */ -var checkIsArray = function(value, type) { - if ( type === void 0 ) type=''; +function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; - if (isArray(value)) { - if (type === '' || trim(type)==='') { - return true; - } - // we test it in reverse - // @TODO if the type is an array (OR) then what? - // we need to take into account this could be an array - var c = value.filter(function (v) { return !combineFn(type)(v); }); - return !(c.length > 0) + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); } - return false -}; +} -/** - * check if it matches the array. pattern - * @param {string} type - * @return {boolean|array} false means NO, always return array - */ -var isArrayLike = function(type) { - // @TODO could that have something like array<> instead of array.<>? missing the dot? - // because type script is Array without the dot - if (type.indexOf(ARRAY_TYPE_LFT) > -1 && type.indexOf(ARRAY_TYPE_RGT) > -1) { - var _type = type.replace(ARRAY_TYPE_LFT, '').replace(ARRAY_TYPE_RGT, ''); - if (_type.indexOf(OR_SEPERATOR)) { - return _type.split(OR_SEPERATOR) - } - return [_type] - } - return false -}; +// Add methods to `ListCache`. +ListCache.prototype.clear = listCacheClear; +ListCache.prototype['delete'] = listCacheDelete; +ListCache.prototype.get = listCacheGet; +ListCache.prototype.has = listCacheHas; +ListCache.prototype.set = listCacheSet; /** - * we might encounter something like array. then we need to take it apart - * @param {object} p the prepared object for processing - * @param {string|array} type the type came from - * @return {boolean} for the filter to operate on + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack */ -var arrayTypeHandler = function(p, type) { - var arg = p.arg; - // need a special case to handle the OR type - // we need to test the args instead of the type(s) - if (type.length > 1) { - return !arg.filter(function (v) { return ( - !(type.length > type.filter(function (t) { return !combineFn(t)(v); }).length) - ); }).length - } - // type is array so this will be or! - return type.length > type.filter(function (t) { return !checkIsArray(arg, t); }).length -}; +function stackClear() { + this.__data__ = new ListCache; + this.size = 0; +} /** - * Creates a unary function that invokes `func` with its argument transformed. + * Removes `key` and its value from the stack. * * @private - * @param {Function} func The function to wrap. - * @param {Function} transform The argument transform. - * @returns {Function} Returns the new function. + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ -function overArg(func, transform) { - return function(arg) { - return func(transform(arg)); - }; -} - -/** Built-in value references. */ -var getPrototype = overArg(Object.getPrototypeOf, Object); - -/** `Object#toString` result references. */ -var objectTag = '[object Object]'; - -/** Used for built-in method references. */ -var funcProto = Function.prototype, - objectProto$2 = Object.prototype; +function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); -/** Used to resolve the decompiled source of functions. */ -var funcToString = funcProto.toString; + this.size = data.size; + return result; +} -/** Used to check objects for own properties. */ -var hasOwnProperty$1 = objectProto$2.hasOwnProperty; +/** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function stackGet(key) { + return this.__data__.get(key); +} -/** Used to infer the `Object` constructor. */ -var objectCtorString = funcToString.call(Object); +/** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function stackHas(key) { + return this.__data__.has(key); +} /** - * Checks if `value` is a plain object, that is, an object created by the - * `Object` constructor or one with a `[[Prototype]]` of `null`. + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ - * @since 0.8.0 + * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. * @example * - * function Foo() { - * this.a = 1; - * } + * _.isObject({}); + * // => true * - * _.isPlainObject(new Foo); - * // => false + * _.isObject([1, 2, 3]); + * // => true * - * _.isPlainObject([1, 2, 3]); + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); * // => false + */ +function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); +} + +/** `Object#toString` result references. */ +var asyncTag = '[object AsyncFunction]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + proxyTag = '[object Proxy]'; + +/** + * Checks if `value` is classified as a `Function` object. * - * _.isPlainObject({ 'x': 0, 'y': 0 }); - * // => true + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example * - * _.isPlainObject(Object.create(null)); + * _.isFunction(_); * // => true + * + * _.isFunction(/abc/); + * // => false */ -function isPlainObject(value) { - if (!isObjectLike(value) || baseGetTag(value) != objectTag) { +function isFunction(value) { + if (!isObject(value)) { return false; } - var proto = getPrototype(value); - if (proto === null) { - return true; - } - var Ctor = hasOwnProperty$1.call(proto, 'constructor') && proto.constructor; - return typeof Ctor == 'function' && Ctor instanceof Ctor && - funcToString.call(Ctor) == objectCtorString; + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; } -// validate object type -/** - * @TODO if provide with the keys then we need to check if the key:value type as well - * @param {object} value expected - * @param {array} [keys=null] if it has the keys array to compare as well - * @return {boolean} true if OK - */ -var checkIsObject = function(value, keys) { - if ( keys === void 0 ) keys=null; +/** Used to detect overreaching core-js shims. */ +var coreJsData = root['__core-js_shared__']; - if (isPlainObject(value)) { - if (!keys) { - return true - } - if (checkIsArray(keys)) { - // please note we DON'T care if some is optional - // plese refer to the contract.json for the keys - return !keys.filter(function (key) { - var _value = value[key.name]; - return !(key.type.length > key.type.filter(function (type) { - var tmp; - if (_value !== undefined) { - if ((tmp = isArrayLike(type)) !== false) { - return !arrayTypeHandler({arg: _value}, tmp) - // return tmp.filter(t => !checkIsArray(_value, t)).length; - // @TODO there might be an object within an object with keys as well :S - } - return !combineFn(type)(_value) - } - return true - }).length) - }).length; - } - } - return false -}; +/** Used to detect methods masquerading as native. */ +var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; +}()); /** - * fold this into it's own function to handler different object type - * @param {object} p the prepared object for process - * @return {boolean} + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. */ -var objectTypeHandler = function(p) { - var arg = p.arg; - var param = p.param; - var _args = [arg]; - if (Array.isArray(param.keys) && param.keys.length) { - _args.push(param.keys); - } - // just simple check - return Reflect.apply(checkIsObject, null, _args) -}; - -// custom validation error class -// when validaton failed -var JsonqlValidationError = /*@__PURE__*/(function (Error) { - function JsonqlValidationError() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - Error.apply(this, args); +function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); +} - this.message = args[0]; - this.detail = args[1]; +/** Used for built-in method references. */ +var funcProto$1 = Function.prototype; - this.className = JsonqlValidationError.name; +/** Used to resolve the decompiled source of functions. */ +var funcToString$1 = funcProto$1.toString; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlValidationError); - } +/** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ +function toSource(func) { + if (func != null) { + try { + return funcToString$1.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} } + return ''; +} - if ( Error ) JsonqlValidationError.__proto__ = Error; - JsonqlValidationError.prototype = Object.create( Error && Error.prototype ); - JsonqlValidationError.prototype.constructor = JsonqlValidationError; +/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; - var staticAccessors = { name: { configurable: true } }; +/** Used to detect host constructors (Safari). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; - staticAccessors.name.get = function () { - return 'JsonqlValidationError' - }; +/** Used for built-in method references. */ +var funcProto$2 = Function.prototype, + objectProto$3 = Object.prototype; - Object.defineProperties( JsonqlValidationError, staticAccessors ); +/** Used to resolve the decompiled source of functions. */ +var funcToString$2 = funcProto$2.toString; - return JsonqlValidationError; -}(Error)); +/** Used to check objects for own properties. */ +var hasOwnProperty$2 = objectProto$3.hasOwnProperty; -var NO_ERROR_MSG = 'No message'; -var NO_STATUS_CODE = -1; -var UNAUTHORIZED_STATUS = 401; -var FORBIDDEN_STATUS = 403; -var NOT_FOUND_STATUS = 404; -var NOT_ACCEPTABLE_STATUS = 406; -var SERVER_INTERNAL_STATUS = 500; +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + funcToString$2.call(hasOwnProperty$2).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); /** - * This is a custom error to throw whenever a error happen inside the jsonql - * This help us to capture the right error, due to the call happens in sequence - * @param {string} message to tell what happen - * @param {mixed} extra things we want to add, 500? - */ -var JsonqlError$1 = /*@__PURE__*/(function (Error) { - function JsonqlError() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ +function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); +} - Error.apply(this, args); +/** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ +function getValue(object, key) { + return object == null ? undefined : object[key]; +} - this.message = args[0]; - this.detail = args[1]; +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; +} - this.className = JsonqlError.name; +/* Built-in method references that are verified to be native. */ +var Map$1 = getNative(root, 'Map'); - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlError); - // this.detail = this.stack; - } - } +/* Built-in method references that are verified to be native. */ +var nativeCreate = getNative(Object, 'create'); - if ( Error ) JsonqlError.__proto__ = Error; - JsonqlError.prototype = Object.create( Error && Error.prototype ); - JsonqlError.prototype.constructor = JsonqlError; +/** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ +function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; +} - var staticAccessors = { name: { configurable: true },statusCode: { configurable: true } }; +/** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; +} - staticAccessors.name.get = function () { - return 'JsonqlError' - }; +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; - staticAccessors.statusCode.get = function () { - return NO_STATUS_CODE - }; +/** Used for built-in method references. */ +var objectProto$4 = Object.prototype; - Object.defineProperties( JsonqlError, staticAccessors ); +/** Used to check objects for own properties. */ +var hasOwnProperty$3 = objectProto$4.hasOwnProperty; - return JsonqlError; -}(Error)); +/** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty$3.call(data, key) ? data[key] : undefined; +} -// move the index.js code here that make more sense to find where things are -// import debug from 'debug' -// const debugFn = debug('jsonql-params-validator:validator') -// also export this for use in other places +/** Used for built-in method references. */ +var objectProto$5 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$4 = objectProto$5.hasOwnProperty; /** - * We need to handle those optional parameter without a default value - * @param {object} params from contract.json - * @return {boolean} for filter operation false is actually OK + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ -var optionalHandler = function( params ) { - var arg = params.arg; - var param = params.param; - if (isNotEmpty(arg)) { - // debug('call optional handler', arg, params); - // loop through the type in param - return !(param.type.length > param.type.filter(function (type) { return validateHandler(type, params); } - ).length) - } - return false -}; +function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty$4.call(data, key); +} + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED$1 = '__lodash_hash_undefined__'; /** - * actually picking the validator - * @param {*} type for checking - * @param {*} value for checking - * @return {boolean} true on OK + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. */ -var validateHandler = function(type, value) { - var tmp; - switch (true) { - case type === OBJECT_TYPE: - // debugFn('call OBJECT_TYPE') - return !objectTypeHandler(value) - case type === ARRAY_TYPE: - // debugFn('call ARRAY_TYPE') - return !checkIsArray(value.arg) - // @TODO when the type is not present, it always fall through here - // so we need to find a way to actually pre-check the type first - // AKA check the contract.json map before running here - case (tmp = isArrayLike(type)) !== false: - // debugFn('call ARRAY_LIKE: %O', value) - return !arrayTypeHandler(value, tmp) - default: - return !combineFn(type)(value.arg) - } -}; +function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED$1 : value; + return this; +} /** - * it get too longer to fit in one line so break it out from the fn below - * @param {*} arg value - * @param {object} param config - * @return {*} value or apply default value + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. */ -var getOptionalValue = function(arg, param) { - if (arg !== undefined) { - return arg +function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); } - return (param.optional === true && param.defaultvalue !== undefined ? param.defaultvalue : null) -}; +} + +// Add methods to `Hash`. +Hash.prototype.clear = hashClear; +Hash.prototype['delete'] = hashDelete; +Hash.prototype.get = hashGet; +Hash.prototype.has = hashHas; +Hash.prototype.set = hashSet; /** - * padding the arguments with defaultValue if the arguments did not provide the value - * this will be the name export - * @param {array} args normalized arguments - * @param {array} params from contract.json - * @return {array} merge the two together + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache */ -var normalizeArgs = function(args, params) { - // first we should check if this call require a validation at all - // there will be situation where the function doesn't need args and params - if (!checkIsArray(params)) { - // debugFn('params value', params) - throw new JsonqlValidationError(PARAMS_NOT_ARRAY_ERR) - } - if (params.length === 0) { - return [] - } - if (!checkIsArray(args)) { - throw new JsonqlValidationError(ARGS_NOT_ARRAY_ERR) - } - // debugFn(args, params); - // fall through switch - switch(true) { - case args.length == params.length: // standard - return args.map(function (arg, i) { return ( - { - arg: arg, - index: i, - param: params[i] - } - ); }) - case params[0].variable === true: // using spread syntax - var type = params[0].type; - return args.map(function (arg, i) { return ( - { - arg: arg, - index: i, // keep the index for reference - param: params[i] || { type: type, name: '_' } - } - ); }) - // with optional defaultValue parameters - case args.length < params.length: - return params.map(function (param, i) { return ( - { - param: param, - index: i, - arg: getOptionalValue(args[i], param), - optional: param.optional || false - } - ); }) - // this one pass more than it should have anything after the args.length will be cast as any type - case args.length > params.length: - var ctn = params.length; - // this happens when we have those array. type - var _type = [ DEFAULT_TYPE ]; - // we only looking at the first one, this might be a @BUG - /* - if ((tmp = isArrayLike(params[0].type[0])) !== false) { - _type = tmp; - } */ - // if we use the params as guide then the rest will get throw out - // which is not what we want, instead, anything without the param - // will get a any type and optional flag - return args.map(function (arg, i) { - var optional = i >= ctn ? true : !!params[i].optional; - var param = params[i] || { type: _type, name: ("_" + i) }; - return { - arg: optional ? getOptionalValue(arg, param) : arg, - index: i, - param: param, - optional: optional - } - }) - // @TODO find out if there is more cases not cover - default: // this should never happen - // debugFn('args', args) - // debugFn('params', params) - // this is unknown therefore we just throw it! - throw new JsonqlError$1(EXCEPTION_CASE_ERR, { args: args, params: params }) - } -}; - -// what we want is after the validaton we also get the normalized result -// which is with the optional property if the argument didn't provide it -/** - * process the array of params back to their arguments - * @param {array} result the params result - * @return {array} arguments - */ -var processReturn = function (result) { return result.map(function (r) { return r.arg; }); }; - -/** - * validator main interface - * @param {array} args the arguments pass to the method call - * @param {array} params from the contract for that method - * @param {boolean} [withResul=false] if true then this will return the normalize result as well - * @return {array} empty array on success, or failed parameter and reasons - */ -var validateSync = function(args, params, withResult) { - var obj; - - if ( withResult === void 0 ) withResult = false; - var cleanArgs = normalizeArgs(args, params); - var checkResult = cleanArgs.filter(function (p) { - // v1.4.4 this fixed the problem, the root level optional is from the last fn - if (p.optional === true || p.param.optional === true) { - return optionalHandler(p) - } - // because array of types means OR so if one pass means pass - return !(p.param.type.length > p.param.type.filter( - function (type) { return validateHandler(type, p); } - ).length) - }); - // using the same convention we been using all this time - return !withResult ? checkResult : ( obj = {}, obj[ERROR_KEY] = checkResult, obj[DATA_KEY] = processReturn(cleanArgs), obj ) -}; - -/** - * A wrapper method that return promise - * @param {array} args arguments - * @param {array} params from contract.json - * @param {boolean} [withResul=false] if true then this will return the normalize result as well - * @return {object} promise.then or catch - */ -var validateAsync = function(args, params, withResult) { - if ( withResult === void 0 ) withResult = false; - - return new Promise(function (resolver, rejecter) { - var result = validateSync(args, params, withResult); - if (withResult) { - return result[ERROR_KEY].length ? rejecter(result[ERROR_KEY]) - : resolver(result[DATA_KEY]) - } - // the different is just in the then or catch phrase - return result.length ? rejecter(result) : resolver([]) - }) -}; - -/** - * Removes all key-value entries from the list cache. - * - * @private - * @name clear - * @memberOf ListCache - */ -function listCacheClear() { - this.__data__ = []; +function mapCacheClear() { this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map$1 || ListCache), + 'string': new Hash + }; } /** - * Performs a - * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * comparison between two values to determine if they are equivalent. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - * @example - * - * var object = { 'a': 1 }; - * var other = { 'a': 1 }; - * - * _.eq(object, object); - * // => true - * - * _.eq(object, other); - * // => false - * - * _.eq('a', 'a'); - * // => true - * - * _.eq('a', Object('a')); - * // => false + * Checks if `value` is suitable for use as unique object key. * - * _.eq(NaN, NaN); - * // => true + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. */ -function eq(value, other) { - return value === other || (value !== value && other !== other); +function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); } /** - * Gets the index at which the `key` is found in `array` of key-value pairs. + * Gets the data for `map`. * * @private - * @param {Array} array The array to inspect. - * @param {*} key The key to search for. - * @returns {number} Returns the index of the matched value, else `-1`. + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. */ -function assocIndexOf(array, key) { - var length = array.length; - while (length--) { - if (eq(array[length][0], key)) { - return length; - } - } - return -1; +function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; } -/** Used for built-in method references. */ -var arrayProto = Array.prototype; - -/** Built-in value references. */ -var splice = arrayProto.splice; - /** - * Removes `key` and its value from the list cache. + * Removes `key` and its value from the map. * * @private * @name delete - * @memberOf ListCache + * @memberOf MapCache * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ -function listCacheDelete(key) { - var data = this.__data__, - index = assocIndexOf(data, key); - - if (index < 0) { - return false; - } - var lastIndex = data.length - 1; - if (index == lastIndex) { - data.pop(); - } else { - splice.call(data, index, 1); - } - --this.size; - return true; +function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; } /** - * Gets the list cache value for `key`. + * Gets the map value for `key`. * * @private * @name get - * @memberOf ListCache + * @memberOf MapCache * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ -function listCacheGet(key) { - var data = this.__data__, - index = assocIndexOf(data, key); - - return index < 0 ? undefined : data[index][1]; +function mapCacheGet(key) { + return getMapData(this, key).get(key); } /** - * Checks if a list cache value for `key` exists. + * Checks if a map value for `key` exists. * * @private * @name has - * @memberOf ListCache + * @memberOf MapCache * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ -function listCacheHas(key) { - return assocIndexOf(this.__data__, key) > -1; +function mapCacheHas(key) { + return getMapData(this, key).has(key); } /** - * Sets the list cache `key` to `value`. + * Sets the map `key` to `value`. * * @private * @name set - * @memberOf ListCache + * @memberOf MapCache * @param {string} key The key of the value to set. * @param {*} value The value to set. - * @returns {Object} Returns the list cache instance. + * @returns {Object} Returns the map cache instance. */ -function listCacheSet(key, value) { - var data = this.__data__, - index = assocIndexOf(data, key); +function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; - if (index < 0) { - ++this.size; - data.push([key, value]); - } else { - data[index][1] = value; - } + data.set(key, value); + this.size += data.size == size ? 0 : 1; return this; } /** - * Creates an list cache object. + * Creates a map cache object to store key-value pairs. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ -function ListCache(entries) { +function MapCache(entries) { var index = -1, length = entries == null ? 0 : entries.length; @@ -1458,5484 +1493,5618 @@ function ListCache(entries) { } } -// Add methods to `ListCache`. -ListCache.prototype.clear = listCacheClear; -ListCache.prototype['delete'] = listCacheDelete; -ListCache.prototype.get = listCacheGet; -ListCache.prototype.has = listCacheHas; -ListCache.prototype.set = listCacheSet; - -/** - * Removes all key-value entries from the stack. +// Add methods to `MapCache`. +MapCache.prototype.clear = mapCacheClear; +MapCache.prototype['delete'] = mapCacheDelete; +MapCache.prototype.get = mapCacheGet; +MapCache.prototype.has = mapCacheHas; +MapCache.prototype.set = mapCacheSet; + +/** Used as the size to enable large array optimizations. */ +var LARGE_ARRAY_SIZE = 200; + +/** + * Sets the stack `key` to `value`. * * @private - * @name clear + * @name set * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. */ -function stackClear() { - this.__data__ = new ListCache; - this.size = 0; +function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map$1 || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; } /** - * Removes `key` and its value from the stack. + * Creates a stack cache object to store key-value pairs. * * @private - * @name delete - * @memberOf Stack - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. + * @constructor + * @param {Array} [entries] The key-value pairs to cache. */ -function stackDelete(key) { - var data = this.__data__, - result = data['delete'](key); - +function Stack(entries) { + var data = this.__data__ = new ListCache(entries); this.size = data.size; - return result; } +// Add methods to `Stack`. +Stack.prototype.clear = stackClear; +Stack.prototype['delete'] = stackDelete; +Stack.prototype.get = stackGet; +Stack.prototype.has = stackHas; +Stack.prototype.set = stackSet; + +var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} +}()); + /** - * Gets the stack value for `key`. + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. * * @private - * @name get - * @memberOf Stack - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. */ -function stackGet(key) { - return this.__data__.get(key); +function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } } /** - * Checks if a stack value for `key` exists. + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. * * @private - * @name has - * @memberOf Stack - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. */ -function stackHas(key) { - return this.__data__.has(key); +function assignMergeValue(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } } /** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(_.noop); - * // => true + * Creates a base function for methods like `_.forIn` and `_.forOwn`. * - * _.isObject(null); - * // => false + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. */ -function isObject(value) { - var type = typeof value; - return value != null && (type == 'object' || type == 'function'); -} +function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; -/** `Object#toString` result references. */ -var asyncTag = '[object AsyncFunction]', - funcTag = '[object Function]', - genTag = '[object GeneratorFunction]', - proxyTag = '[object Proxy]'; + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; +} /** - * Checks if `value` is classified as a `Function` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a function, else `false`. - * @example - * - * _.isFunction(_); - * // => true + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. * - * _.isFunction(/abc/); - * // => false + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. */ -function isFunction(value) { - if (!isObject(value)) { - return false; - } - // The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 9 which returns 'object' for typed arrays and other constructors. - var tag = baseGetTag(value); - return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; -} +var baseFor = createBaseFor(); -/** Used to detect overreaching core-js shims. */ -var coreJsData = root['__core-js_shared__']; +/** Detect free variable `exports`. */ +var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; -/** Used to detect methods masquerading as native. */ -var maskSrcKey = (function() { - var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); - return uid ? ('Symbol(src)_1.' + uid) : ''; -}()); +/** Detect free variable `module`. */ +var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Built-in value references. */ +var Buffer = moduleExports ? root.Buffer : undefined, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined; /** - * Checks if `func` has its source masked. + * Creates a clone of `buffer`. * * @private - * @param {Function} func The function to check. - * @returns {boolean} Returns `true` if `func` is masked, else `false`. + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. */ -function isMasked(func) { - return !!maskSrcKey && (maskSrcKey in func); -} +function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); -/** Used for built-in method references. */ -var funcProto$1 = Function.prototype; + buffer.copy(result); + return result; +} -/** Used to resolve the decompiled source of functions. */ -var funcToString$1 = funcProto$1.toString; +/** Built-in value references. */ +var Uint8Array = root.Uint8Array; /** - * Converts `func` to its source code. + * Creates a clone of `arrayBuffer`. * * @private - * @param {Function} func The function to convert. - * @returns {string} Returns the source code. + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. */ -function toSource(func) { - if (func != null) { - try { - return funcToString$1.call(func); - } catch (e) {} - try { - return (func + ''); - } catch (e) {} - } - return ''; +function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); + return result; } /** - * Used to match `RegExp` - * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). - */ -var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; - -/** Used to detect host constructors (Safari). */ -var reIsHostCtor = /^\[object .+?Constructor\]$/; - -/** Used for built-in method references. */ -var funcProto$2 = Function.prototype, - objectProto$3 = Object.prototype; - -/** Used to resolve the decompiled source of functions. */ -var funcToString$2 = funcProto$2.toString; - -/** Used to check objects for own properties. */ -var hasOwnProperty$2 = objectProto$3.hasOwnProperty; - -/** Used to detect if a method is native. */ -var reIsNative = RegExp('^' + - funcToString$2.call(hasOwnProperty$2).replace(reRegExpChar, '\\$&') - .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' -); - -/** - * The base implementation of `_.isNative` without bad shim checks. + * Creates a clone of `typedArray`. * * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a native function, - * else `false`. + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. */ -function baseIsNative(value) { - if (!isObject(value) || isMasked(value)) { - return false; - } - var pattern = isFunction(value) ? reIsNative : reIsHostCtor; - return pattern.test(toSource(value)); +function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); } /** - * Gets the value at `key` of `object`. + * Copies the values of `source` to `array`. * * @private - * @param {Object} [object] The object to query. - * @param {string} key The key of the property to get. - * @returns {*} Returns the property value. + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. */ -function getValue(object, key) { - return object == null ? undefined : object[key]; +function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; } +/** Built-in value references. */ +var objectCreate = Object.create; + /** - * Gets the native function at `key` of `object`. + * The base implementation of `_.create` without support for assigning + * properties to the created object. * * @private - * @param {Object} object The object to query. - * @param {string} key The key of the method to get. - * @returns {*} Returns the function if it's native, else `undefined`. + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. */ -function getNative(object, key) { - var value = getValue(object, key); - return baseIsNative(value) ? value : undefined; -} - -/* Built-in method references that are verified to be native. */ -var Map$1 = getNative(root, 'Map'); +var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; +}()); -/* Built-in method references that are verified to be native. */ -var nativeCreate = getNative(Object, 'create'); +/** Used for built-in method references. */ +var objectProto$6 = Object.prototype; /** - * Removes all key-value entries from the hash. + * Checks if `value` is likely a prototype object. * * @private - * @name clear - * @memberOf Hash + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. */ -function hashClear() { - this.__data__ = nativeCreate ? nativeCreate(null) : {}; - this.size = 0; +function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto$6; + + return value === proto; } /** - * Removes `key` and its value from the hash. + * Initializes an object clone. * * @private - * @name delete - * @memberOf Hash - * @param {Object} hash The hash to modify. - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. */ -function hashDelete(key) { - var result = this.has(key) && delete this.__data__[key]; - this.size -= result ? 1 : 0; - return result; +function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; } -/** Used to stand-in for `undefined` hash values. */ -var HASH_UNDEFINED = '__lodash_hash_undefined__'; - -/** Used for built-in method references. */ -var objectProto$4 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$3 = objectProto$4.hasOwnProperty; +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]'; /** - * Gets the hash value for `key`. + * The base implementation of `_.isArguments`. * * @private - * @name get - * @memberOf Hash - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, */ -function hashGet(key) { - var data = this.__data__; - if (nativeCreate) { - var result = data[key]; - return result === HASH_UNDEFINED ? undefined : result; - } - return hasOwnProperty$3.call(data, key) ? data[key] : undefined; +function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; } /** Used for built-in method references. */ -var objectProto$5 = Object.prototype; +var objectProto$7 = Object.prototype; /** Used to check objects for own properties. */ -var hasOwnProperty$4 = objectProto$5.hasOwnProperty; +var hasOwnProperty$5 = objectProto$7.hasOwnProperty; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto$7.propertyIsEnumerable; /** - * Checks if a hash value for `key` exists. + * Checks if `value` is likely an `arguments` object. * - * @private - * @name has - * @memberOf Hash - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false */ -function hashHas(key) { - var data = this.__data__; - return nativeCreate ? (data[key] !== undefined) : hasOwnProperty$4.call(data, key); -} +var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty$5.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); +}; -/** Used to stand-in for `undefined` hash values. */ -var HASH_UNDEFINED$1 = '__lodash_hash_undefined__'; +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; /** - * Sets the hash `key` to `value`. + * Checks if `value` is a valid array-like length. * - * @private - * @name set - * @memberOf Hash - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the hash instance. - */ -function hashSet(key, value) { - var data = this.__data__; - this.size += this.has(key) ? 0 : 1; - data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED$1 : value; - return this; -} - -/** - * Creates a hash object. + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false */ -function Hash(entries) { - var index = -1, - length = entries == null ? 0 : entries.length; - - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; } -// Add methods to `Hash`. -Hash.prototype.clear = hashClear; -Hash.prototype['delete'] = hashDelete; -Hash.prototype.get = hashGet; -Hash.prototype.has = hashHas; -Hash.prototype.set = hashSet; - /** - * Removes all key-value entries from the map. + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. * - * @private - * @name clear - * @memberOf MapCache + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false */ -function mapCacheClear() { - this.size = 0; - this.__data__ = { - 'hash': new Hash, - 'map': new (Map$1 || ListCache), - 'string': new Hash - }; +function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); } /** - * Checks if `value` is suitable for use as unique object key. + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. * - * @private + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false */ -function isKeyable(value) { - var type = typeof value; - return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') - ? (value !== '__proto__') - : (value === null); +function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); } /** - * Gets the data for `map`. + * This method returns `false`. * - * @private - * @param {Object} map The map to query. - * @param {string} key The reference key. - * @returns {*} Returns the map data. + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `false`. + * @example + * + * _.times(2, _.stubFalse); + * // => [false, false] */ -function getMapData(map, key) { - var data = map.__data__; - return isKeyable(key) - ? data[typeof key == 'string' ? 'string' : 'hash'] - : data.map; +function stubFalse() { + return false; } +/** Detect free variable `exports`. */ +var freeExports$1 = typeof exports == 'object' && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule$1 = freeExports$1 && typeof module == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports$1 = freeModule$1 && freeModule$1.exports === freeExports$1; + +/** Built-in value references. */ +var Buffer$1 = moduleExports$1 ? root.Buffer : undefined; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeIsBuffer = Buffer$1 ? Buffer$1.isBuffer : undefined; + /** - * Removes `key` and its value from the map. + * Checks if `value` is a buffer. * - * @private - * @name delete - * @memberOf MapCache - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false */ -function mapCacheDelete(key) { - var result = getMapData(this, key)['delete'](key); - this.size -= result ? 1 : 0; - return result; -} +var isBuffer = nativeIsBuffer || stubFalse; + +/** `Object#toString` result references. */ +var argsTag$1 = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag$1 = '[object Function]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag$1 = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + weakMapTag = '[object WeakMap]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** Used to identify `toStringTag` values of typed arrays. */ +var typedArrayTags = {}; +typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = +typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = +typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = +typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = +typedArrayTags[uint32Tag] = true; +typedArrayTags[argsTag$1] = typedArrayTags[arrayTag] = +typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = +typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = +typedArrayTags[errorTag] = typedArrayTags[funcTag$1] = +typedArrayTags[mapTag] = typedArrayTags[numberTag] = +typedArrayTags[objectTag$1] = typedArrayTags[regexpTag] = +typedArrayTags[setTag] = typedArrayTags[stringTag] = +typedArrayTags[weakMapTag] = false; /** - * Gets the map value for `key`. + * The base implementation of `_.isTypedArray` without Node.js optimizations. * * @private - * @name get - * @memberOf MapCache - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. */ -function mapCacheGet(key) { - return getMapData(this, key).get(key); +function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; } /** - * Checks if a map value for `key` exists. + * The base implementation of `_.unary` without support for storing metadata. * * @private - * @name has - * @memberOf MapCache - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. */ -function mapCacheHas(key) { - return getMapData(this, key).has(key); +function baseUnary(func) { + return function(value) { + return func(value); + }; } -/** - * Sets the map `key` to `value`. - * - * @private - * @name set - * @memberOf MapCache - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the map cache instance. - */ -function mapCacheSet(key, value) { - var data = getMapData(this, key), - size = data.size; +/** Detect free variable `exports`. */ +var freeExports$2 = typeof exports == 'object' && exports && !exports.nodeType && exports; - data.set(key, value); - this.size += data.size == size ? 0 : 1; - return this; -} +/** Detect free variable `module`. */ +var freeModule$2 = freeExports$2 && typeof module == 'object' && module && !module.nodeType && module; -/** - * Creates a map cache object to store key-value pairs. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ -function MapCache(entries) { - var index = -1, - length = entries == null ? 0 : entries.length; +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports$2 = freeModule$2 && freeModule$2.exports === freeExports$2; - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } -} +/** Detect free variable `process` from Node.js. */ +var freeProcess = moduleExports$2 && freeGlobal.process; -// Add methods to `MapCache`. -MapCache.prototype.clear = mapCacheClear; -MapCache.prototype['delete'] = mapCacheDelete; -MapCache.prototype.get = mapCacheGet; -MapCache.prototype.has = mapCacheHas; -MapCache.prototype.set = mapCacheSet; +/** Used to access faster Node.js helpers. */ +var nodeUtil = (function() { + try { + // Use `util.types` for Node.js 10+. + var types = freeModule$2 && freeModule$2.require && freeModule$2.require('util').types; -/** Used as the size to enable large array optimizations. */ -var LARGE_ARRAY_SIZE = 200; + if (types) { + return types; + } + + // Legacy `process.binding('util')` for Node.js < 10. + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} +}()); + +/* Node.js helper references. */ +var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; /** - * Sets the stack `key` to `value`. + * Checks if `value` is classified as a typed array. * - * @private - * @name set - * @memberOf Stack - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the stack cache instance. - */ -function stackSet(key, value) { - var data = this.__data__; - if (data instanceof ListCache) { - var pairs = data.__data__; - if (!Map$1 || (pairs.length < LARGE_ARRAY_SIZE - 1)) { - pairs.push([key, value]); - this.size = ++data.size; - return this; - } - data = this.__data__ = new MapCache(pairs); - } - data.set(key, value); - this.size = data.size; - return this; -} - -/** - * Creates a stack cache object to store key-value pairs. + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false */ -function Stack(entries) { - var data = this.__data__ = new ListCache(entries); - this.size = data.size; -} - -// Add methods to `Stack`. -Stack.prototype.clear = stackClear; -Stack.prototype['delete'] = stackDelete; -Stack.prototype.get = stackGet; -Stack.prototype.has = stackHas; -Stack.prototype.set = stackSet; - -var defineProperty = (function() { - try { - var func = getNative(Object, 'defineProperty'); - func({}, '', {}); - return func; - } catch (e) {} -}()); +var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; /** - * The base implementation of `assignValue` and `assignMergeValue` without - * value checks. + * Gets the value at `key`, unless `key` is "__proto__" or "constructor". * * @private - * @param {Object} object The object to modify. - * @param {string} key The key of the property to assign. - * @param {*} value The value to assign. + * @param {Object} object The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. */ -function baseAssignValue(object, key, value) { - if (key == '__proto__' && defineProperty) { - defineProperty(object, key, { - 'configurable': true, - 'enumerable': true, - 'value': value, - 'writable': true - }); - } else { - object[key] = value; +function safeGet(object, key) { + if (key === 'constructor' && typeof object[key] === 'function') { + return; + } + + if (key == '__proto__') { + return; } + + return object[key]; } +/** Used for built-in method references. */ +var objectProto$8 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$6 = objectProto$8.hasOwnProperty; + /** - * This function is like `assignValue` except that it doesn't assign - * `undefined` values. + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. * * @private * @param {Object} object The object to modify. * @param {string} key The key of the property to assign. * @param {*} value The value to assign. */ -function assignMergeValue(object, key, value) { - if ((value !== undefined && !eq(object[key], value)) || +function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty$6.call(object, key) && eq(objValue, value)) || (value === undefined && !(key in object))) { baseAssignValue(object, key, value); } } /** - * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * Copies properties of `source` to `object`. * * @private - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {Function} Returns the new base function. + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. */ -function createBaseFor(fromRight) { - return function(object, iteratee, keysFunc) { - var index = -1, - iterable = Object(object), - props = keysFunc(object), - length = props.length; +function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); - while (length--) { - var key = props[fromRight ? length : ++index]; - if (iteratee(iterable[key], key, iterable) === false) { - break; - } + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; } - return object; - }; + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; } /** - * The base implementation of `baseForOwn` which iterates over `object` - * properties returned by `keysFunc` and invokes `iteratee` for each property. - * Iteratee functions may exit iteration early by explicitly returning `false`. + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. * * @private - * @param {Object} object The object to iterate over. + * @param {number} n The number of times to invoke `iteratee`. * @param {Function} iteratee The function invoked per iteration. - * @param {Function} keysFunc The function to get the keys of `object`. - * @returns {Object} Returns `object`. + * @returns {Array} Returns the array of results. */ -var baseFor = createBaseFor(); - -/** Detect free variable `exports`. */ -var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; +function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); -/** Detect free variable `module`. */ -var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} -/** Detect the popular CommonJS extension `module.exports`. */ -var moduleExports = freeModule && freeModule.exports === freeExports; +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER$1 = 9007199254740991; -/** Built-in value references. */ -var Buffer = moduleExports ? root.Buffer : undefined, - allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined; +/** Used to detect unsigned integer values. */ +var reIsUint = /^(?:0|[1-9]\d*)$/; /** - * Creates a clone of `buffer`. + * Checks if `value` is a valid array-like index. * * @private - * @param {Buffer} buffer The buffer to clone. - * @param {boolean} [isDeep] Specify a deep clone. - * @returns {Buffer} Returns the cloned buffer. + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. */ -function cloneBuffer(buffer, isDeep) { - if (isDeep) { - return buffer.slice(); - } - var length = buffer.length, - result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); +function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER$1 : length; - buffer.copy(result); - return result; + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); } -/** Built-in value references. */ -var Uint8Array = root.Uint8Array; +/** Used for built-in method references. */ +var objectProto$9 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$7 = objectProto$9.hasOwnProperty; /** - * Creates a clone of `arrayBuffer`. + * Creates an array of the enumerable property names of the array-like `value`. * * @private - * @param {ArrayBuffer} arrayBuffer The array buffer to clone. - * @returns {ArrayBuffer} Returns the cloned array buffer. + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. */ -function cloneArrayBuffer(arrayBuffer) { - var result = new arrayBuffer.constructor(arrayBuffer.byteLength); - new Uint8Array(result).set(new Uint8Array(arrayBuffer)); +function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty$7.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } return result; } /** - * Creates a clone of `typedArray`. + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. * * @private - * @param {Object} typedArray The typed array to clone. - * @param {boolean} [isDeep] Specify a deep clone. - * @returns {Object} Returns the cloned typed array. + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. */ -function cloneTypedArray(typedArray, isDeep) { - var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; - return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); -} - -/** - * Copies the values of `source` to `array`. - * - * @private - * @param {Array} source The array to copy values from. - * @param {Array} [array=[]] The array to copy values to. - * @returns {Array} Returns `array`. - */ -function copyArray(source, array) { - var index = -1, - length = source.length; - - array || (array = Array(length)); - while (++index < length) { - array[index] = source[index]; +function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } } - return array; + return result; } -/** Built-in value references. */ -var objectCreate = Object.create; - -/** - * The base implementation of `_.create` without support for assigning - * properties to the created object. - * - * @private - * @param {Object} proto The object to inherit from. - * @returns {Object} Returns the new object. - */ -var baseCreate = (function() { - function object() {} - return function(proto) { - if (!isObject(proto)) { - return {}; - } - if (objectCreate) { - return objectCreate(proto); - } - object.prototype = proto; - var result = new object; - object.prototype = undefined; - return result; - }; -}()); - /** Used for built-in method references. */ -var objectProto$6 = Object.prototype; - -/** - * Checks if `value` is likely a prototype object. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. - */ -function isPrototype(value) { - var Ctor = value && value.constructor, - proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto$6; +var objectProto$a = Object.prototype; - return value === proto; -} +/** Used to check objects for own properties. */ +var hasOwnProperty$8 = objectProto$a.hasOwnProperty; /** - * Initializes an object clone. + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. * * @private - * @param {Object} object The object to clone. - * @returns {Object} Returns the initialized clone. + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. */ -function initCloneObject(object) { - return (typeof object.constructor == 'function' && !isPrototype(object)) - ? baseCreate(getPrototype(object)) - : {}; -} - -/** `Object#toString` result references. */ -var argsTag = '[object Arguments]'; +function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; -/** - * The base implementation of `_.isArguments`. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an `arguments` object, - */ -function baseIsArguments(value) { - return isObjectLike(value) && baseGetTag(value) == argsTag; + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty$8.call(object, key)))) { + result.push(key); + } + } + return result; } -/** Used for built-in method references. */ -var objectProto$7 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$5 = objectProto$7.hasOwnProperty; - -/** Built-in value references. */ -var propertyIsEnumerable = objectProto$7.propertyIsEnumerable; - -/** - * Checks if `value` is likely an `arguments` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an `arguments` object, - * else `false`. - * @example - * - * _.isArguments(function() { return arguments; }()); - * // => true - * - * _.isArguments([1, 2, 3]); - * // => false - */ -var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { - return isObjectLike(value) && hasOwnProperty$5.call(value, 'callee') && - !propertyIsEnumerable.call(value, 'callee'); -}; - -/** Used as references for various `Number` constants. */ -var MAX_SAFE_INTEGER = 9007199254740991; - /** - * Checks if `value` is a valid array-like length. + * Creates an array of the own and inherited enumerable property names of `object`. * - * **Note:** This method is loosely based on - * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. * @example * - * _.isLength(3); - * // => true - * - * _.isLength(Number.MIN_VALUE); - * // => false + * function Foo() { + * this.a = 1; + * this.b = 2; + * } * - * _.isLength(Infinity); - * // => false + * Foo.prototype.c = 3; * - * _.isLength('3'); - * // => false + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) */ -function isLength(value) { - return typeof value == 'number' && - value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); } /** - * Checks if `value` is array-like. A value is considered array-like if it's - * not a function and has a `value.length` that's an integer greater than or - * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * Converts `value` to a plain object flattening inherited enumerable string + * keyed properties of `value` to own properties of the plain object. * * @static * @memberOf _ - * @since 4.0.0 + * @since 3.0.0 * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @param {*} value The value to convert. + * @returns {Object} Returns the converted plain object. * @example * - * _.isArrayLike([1, 2, 3]); - * // => true + * function Foo() { + * this.b = 2; + * } * - * _.isArrayLike(document.body.children); - * // => true + * Foo.prototype.c = 3; * - * _.isArrayLike('abc'); - * // => true + * _.assign({ 'a': 1 }, new Foo); + * // => { 'a': 1, 'b': 2 } * - * _.isArrayLike(_.noop); - * // => false + * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); + * // => { 'a': 1, 'b': 2, 'c': 3 } */ -function isArrayLike$1(value) { - return value != null && isLength(value.length) && !isFunction(value); +function toPlainObject(value) { + return copyObject(value, keysIn(value)); } /** - * This method is like `_.isArrayLike` except that it also checks if `value` - * is an object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array-like object, - * else `false`. - * @example - * - * _.isArrayLikeObject([1, 2, 3]); - * // => true - * - * _.isArrayLikeObject(document.body.children); - * // => true - * - * _.isArrayLikeObject('abc'); - * // => false + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. * - * _.isArrayLikeObject(_.noop); - * // => false + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize assigned values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. */ -function isArrayLikeObject(value) { - return isObjectLike(value) && isArrayLike$1(value); -} +function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = safeGet(object, key), + srcValue = safeGet(source, key), + stacked = stack.get(srcValue); -/** - * This method returns `false`. - * - * @static - * @memberOf _ - * @since 4.13.0 - * @category Util - * @returns {boolean} Returns `false`. - * @example - * - * _.times(2, _.stubFalse); - * // => [false, false] - */ -function stubFalse() { - return false; -} + if (stacked) { + assignMergeValue(object, key, stacked); + return; + } + var newValue = customizer + ? customizer(objValue, srcValue, (key + ''), object, source, stack) + : undefined; -/** Detect free variable `exports`. */ -var freeExports$1 = typeof exports == 'object' && exports && !exports.nodeType && exports; + var isCommon = newValue === undefined; -/** Detect free variable `module`. */ -var freeModule$1 = freeExports$1 && typeof module == 'object' && module && !module.nodeType && module; + if (isCommon) { + var isArr = isArray(srcValue), + isBuff = !isArr && isBuffer(srcValue), + isTyped = !isArr && !isBuff && isTypedArray(srcValue); -/** Detect the popular CommonJS extension `module.exports`. */ -var moduleExports$1 = freeModule$1 && freeModule$1.exports === freeExports$1; + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray(objValue)) { + newValue = objValue; + } + else if (isArrayLikeObject(objValue)) { + newValue = copyArray(objValue); + } + else if (isBuff) { + isCommon = false; + newValue = cloneBuffer(srcValue, true); + } + else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray(srcValue, true); + } + else { + newValue = []; + } + } + else if (isPlainObject(srcValue) || isArguments(srcValue)) { + newValue = objValue; + if (isArguments(objValue)) { + newValue = toPlainObject(objValue); + } + else if (!isObject(objValue) || isFunction(objValue)) { + newValue = initCloneObject(srcValue); + } + } + else { + isCommon = false; + } + } + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack['delete'](srcValue); + } + assignMergeValue(object, key, newValue); +} -/** Built-in value references. */ -var Buffer$1 = moduleExports$1 ? root.Buffer : undefined; +/** + * The base implementation of `_.merge` without support for multiple sources. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. + * @param {Function} [customizer] The function to customize merged values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ +function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor(source, function(srcValue, key) { + stack || (stack = new Stack); + if (isObject(srcValue)) { + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); + } + else { + var newValue = customizer + ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack) + : undefined; -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeIsBuffer = Buffer$1 ? Buffer$1.isBuffer : undefined; + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); +} /** - * Checks if `value` is a buffer. + * This method returns the first argument it receives. * * @static + * @since 0.1.0 * @memberOf _ - * @since 4.3.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @category Util + * @param {*} value Any value. + * @returns {*} Returns `value`. * @example * - * _.isBuffer(new Buffer(2)); - * // => true + * var object = { 'a': 1 }; * - * _.isBuffer(new Uint8Array(2)); - * // => false + * console.log(_.identity(object) === object); + * // => true */ -var isBuffer = nativeIsBuffer || stubFalse; - -/** `Object#toString` result references. */ -var argsTag$1 = '[object Arguments]', - arrayTag = '[object Array]', - boolTag = '[object Boolean]', - dateTag = '[object Date]', - errorTag = '[object Error]', - funcTag$1 = '[object Function]', - mapTag = '[object Map]', - numberTag$1 = '[object Number]', - objectTag$1 = '[object Object]', - regexpTag = '[object RegExp]', - setTag = '[object Set]', - stringTag$1 = '[object String]', - weakMapTag = '[object WeakMap]'; - -var arrayBufferTag = '[object ArrayBuffer]', - dataViewTag = '[object DataView]', - float32Tag = '[object Float32Array]', - float64Tag = '[object Float64Array]', - int8Tag = '[object Int8Array]', - int16Tag = '[object Int16Array]', - int32Tag = '[object Int32Array]', - uint8Tag = '[object Uint8Array]', - uint8ClampedTag = '[object Uint8ClampedArray]', - uint16Tag = '[object Uint16Array]', - uint32Tag = '[object Uint32Array]'; - -/** Used to identify `toStringTag` values of typed arrays. */ -var typedArrayTags = {}; -typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = -typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = -typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = -typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = -typedArrayTags[uint32Tag] = true; -typedArrayTags[argsTag$1] = typedArrayTags[arrayTag] = -typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = -typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = -typedArrayTags[errorTag] = typedArrayTags[funcTag$1] = -typedArrayTags[mapTag] = typedArrayTags[numberTag$1] = -typedArrayTags[objectTag$1] = typedArrayTags[regexpTag] = -typedArrayTags[setTag] = typedArrayTags[stringTag$1] = -typedArrayTags[weakMapTag] = false; +function identity(value) { + return value; +} /** - * The base implementation of `_.isTypedArray` without Node.js optimizations. + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. * * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. */ -function baseIsTypedArray(value) { - return isObjectLike(value) && - isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; +function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); } +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + /** - * The base implementation of `_.unary` without support for storing metadata. + * A specialized version of `baseRest` which transforms the rest array. * * @private - * @param {Function} func The function to cap arguments for. - * @returns {Function} Returns the new capped function. + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. */ -function baseUnary(func) { - return function(value) { - return func(value); - }; -} - -/** Detect free variable `exports`. */ -var freeExports$2 = typeof exports == 'object' && exports && !exports.nodeType && exports; - -/** Detect free variable `module`. */ -var freeModule$2 = freeExports$2 && typeof module == 'object' && module && !module.nodeType && module; - -/** Detect the popular CommonJS extension `module.exports`. */ -var moduleExports$2 = freeModule$2 && freeModule$2.exports === freeExports$2; - -/** Detect free variable `process` from Node.js. */ -var freeProcess = moduleExports$2 && freeGlobal.process; - -/** Used to access faster Node.js helpers. */ -var nodeUtil = (function() { - try { - // Use `util.types` for Node.js 10+. - var types = freeModule$2 && freeModule$2.require && freeModule$2.require('util').types; +function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); - if (types) { - return types; + while (++index < length) { + array[index] = args[start + index]; } - - // Legacy `process.binding('util')` for Node.js < 10. - return freeProcess && freeProcess.binding && freeProcess.binding('util'); - } catch (e) {} -}()); - -/* Node.js helper references. */ -var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; +} /** - * Checks if `value` is classified as a typed array. + * Creates a function that returns `value`. * * @static * @memberOf _ - * @since 3.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @since 2.4.0 + * @category Util + * @param {*} value The value to return from the new function. + * @returns {Function} Returns the new constant function. * @example * - * _.isTypedArray(new Uint8Array); - * // => true + * var objects = _.times(2, _.constant({ 'a': 1 })); * - * _.isTypedArray([]); - * // => false - */ -var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; - -/** - * Gets the value at `key`, unless `key` is "__proto__" or "constructor". + * console.log(objects); + * // => [{ 'a': 1 }, { 'a': 1 }] * - * @private - * @param {Object} object The object to query. - * @param {string} key The key of the property to get. - * @returns {*} Returns the property value. + * console.log(objects[0] === objects[1]); + * // => true */ -function safeGet(object, key) { - if (key === 'constructor' && typeof object[key] === 'function') { - return; - } - - if (key == '__proto__') { - return; - } - - return object[key]; +function constant(value) { + return function() { + return value; + }; } -/** Used for built-in method references. */ -var objectProto$8 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$6 = objectProto$8.hasOwnProperty; - /** - * Assigns `value` to `key` of `object` if the existing value is not equivalent - * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. + * The base implementation of `setToString` without support for hot loop shorting. * * @private - * @param {Object} object The object to modify. - * @param {string} key The key of the property to assign. - * @param {*} value The value to assign. + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. */ -function assignValue(object, key, value) { - var objValue = object[key]; - if (!(hasOwnProperty$6.call(object, key) && eq(objValue, value)) || - (value === undefined && !(key in object))) { - baseAssignValue(object, key, value); - } -} +var baseSetToString = !defineProperty ? identity : function(func, string) { + return defineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); +}; + +/** Used to detect hot functions by number of calls within a span of milliseconds. */ +var HOT_COUNT = 800, + HOT_SPAN = 16; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeNow = Date.now; /** - * Copies properties of `source` to `object`. + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. * * @private - * @param {Object} source The object to copy properties from. - * @param {Array} props The property identifiers to copy. - * @param {Object} [object={}] The object to copy properties to. - * @param {Function} [customizer] The function to customize copied values. - * @returns {Object} Returns `object`. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. */ -function copyObject(source, props, object, customizer) { - var isNew = !object; - object || (object = {}); - - var index = -1, - length = props.length; - - while (++index < length) { - var key = props[index]; +function shortOut(func) { + var count = 0, + lastCalled = 0; - var newValue = customizer - ? customizer(object[key], source[key], key, object, source) - : undefined; + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); - if (newValue === undefined) { - newValue = source[key]; - } - if (isNew) { - baseAssignValue(object, key, newValue); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } } else { - assignValue(object, key, newValue); + count = 0; } - } - return object; + return func.apply(undefined, arguments); + }; } /** - * The base implementation of `_.times` without support for iteratee shorthands - * or max array length checks. + * Sets the `toString` method of `func` to return `string`. * * @private - * @param {number} n The number of times to invoke `iteratee`. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Array} Returns the array of results. + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. */ -function baseTimes(n, iteratee) { - var index = -1, - result = Array(n); - - while (++index < n) { - result[index] = iteratee(index); - } - return result; -} - -/** Used as references for various `Number` constants. */ -var MAX_SAFE_INTEGER$1 = 9007199254740991; - -/** Used to detect unsigned integer values. */ -var reIsUint = /^(?:0|[1-9]\d*)$/; +var setToString = shortOut(baseSetToString); /** - * Checks if `value` is a valid array-like index. + * The base implementation of `_.rest` which doesn't validate or coerce arguments. * * @private - * @param {*} value The value to check. - * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. - * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. */ -function isIndex(value, length) { - var type = typeof value; - length = length == null ? MAX_SAFE_INTEGER$1 : length; - - return !!length && - (type == 'number' || - (type != 'symbol' && reIsUint.test(value))) && - (value > -1 && value % 1 == 0 && value < length); +function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); } -/** Used for built-in method references. */ -var objectProto$9 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$7 = objectProto$9.hasOwnProperty; - /** - * Creates an array of the enumerable property names of the array-like `value`. + * Checks if the given arguments are from an iteratee call. * * @private - * @param {*} value The value to query. - * @param {boolean} inherited Specify returning inherited property names. - * @returns {Array} Returns the array of property names. + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. */ -function arrayLikeKeys(value, inherited) { - var isArr = isArray(value), - isArg = !isArr && isArguments(value), - isBuff = !isArr && !isArg && isBuffer(value), - isType = !isArr && !isArg && !isBuff && isTypedArray(value), - skipIndexes = isArr || isArg || isBuff || isType, - result = skipIndexes ? baseTimes(value.length, String) : [], - length = result.length; - - for (var key in value) { - if ((inherited || hasOwnProperty$7.call(value, key)) && - !(skipIndexes && ( - // Safari 9 has enumerable `arguments.length` in strict mode. - key == 'length' || - // Node.js 0.10 has enumerable non-index properties on buffers. - (isBuff && (key == 'offset' || key == 'parent')) || - // PhantomJS 2 has enumerable non-index properties on typed arrays. - (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || - // Skip index properties. - isIndex(key, length) - ))) { - result.push(key); - } +function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; } - return result; + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; } /** - * This function is like - * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) - * except that it includes inherited enumerable properties. + * Creates a function like `_.assign`. * * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. */ -function nativeKeysIn(object) { - var result = []; - if (object != null) { - for (var key in Object(object)) { - result.push(key); - } - } - return result; -} +function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; -/** Used for built-in method references. */ -var objectProto$a = Object.prototype; + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; -/** Used to check objects for own properties. */ -var hasOwnProperty$8 = objectProto$a.hasOwnProperty; + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); +} /** - * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * This method is like `_.assign` except that it recursively merges own and + * inherited enumerable string keyed properties of source objects into the + * destination object. Source properties that resolve to `undefined` are + * skipped if a destination value exists. Array and plain object properties + * are merged recursively. Other objects and value types are overridden by + * assignment. Source objects are applied from left to right. Subsequent + * sources overwrite property assignments of previous sources. * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - */ -function baseKeysIn(object) { - if (!isObject(object)) { - return nativeKeysIn(object); - } - var isProto = isPrototype(object), - result = []; - - for (var key in object) { - if (!(key == 'constructor' && (isProto || !hasOwnProperty$8.call(object, key)))) { - result.push(key); - } - } - return result; -} - -/** - * Creates an array of the own and inherited enumerable property names of `object`. - * - * **Note:** Non-object values are coerced to objects. + * **Note:** This method mutates `object`. * * @static * @memberOf _ - * @since 3.0.0 + * @since 0.5.0 * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. * @example * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } + * var object = { + * 'a': [{ 'b': 2 }, { 'd': 4 }] + * }; * - * Foo.prototype.c = 3; + * var other = { + * 'a': [{ 'c': 3 }, { 'e': 5 }] + * }; * - * _.keysIn(new Foo); - * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + * _.merge(object, other); + * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } */ -function keysIn(object) { - return isArrayLike$1(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); -} +var merge = createAssigner(function(object, source, srcIndex) { + baseMerge(object, source, srcIndex); +}); /** - * Converts `value` to a plain object flattening inherited enumerable string - * keyed properties of `value` to own properties of the plain object. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {Object} Returns the converted plain object. - * @example - * - * function Foo() { - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.assign({ 'a': 1 }, new Foo); - * // => { 'a': 1, 'b': 2 } - * - * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); - * // => { 'a': 1, 'b': 2, 'c': 3 } + * this is essentially the same as the injectToFn + * but this will not allow overwrite and set the setter and getter + * @param {object} obj to get injected + * @param {string} name of the property + * @param {function} setter for set + * @param {function} [getter=null] for get default return null fn + * @return {object} the injected obj */ -function toPlainObject(value) { - return copyObject(value, keysIn(value)); +function objDefineProps(obj, name, setter, getter) { + if ( getter === void 0 ) getter = null; + + if (Object.getOwnPropertyDescriptor(obj, name) === undefined) { + Object.defineProperty(obj, name, { + set: setter, + get: getter === null ? function() { return null; } : getter + }); + } + return obj } /** - * A specialized version of `baseMerge` for arrays and objects which performs - * deep merges and tracks traversed objects enabling objects with circular - * references to be merged. - * - * @private - * @param {Object} object The destination object. - * @param {Object} source The source object. - * @param {string} key The key of the value to merge. - * @param {number} srcIndex The index of `source`. - * @param {Function} mergeFunc The function to merge values. - * @param {Function} [customizer] The function to customize assigned values. - * @param {Object} [stack] Tracks traversed source values and their merged - * counterparts. + * check if the object has name property + * @param {object} obj the object to check + * @param {string} name the prop name + * @return {*} the value or undefined */ -function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { - var objValue = safeGet(object, key), - srcValue = safeGet(source, key), - stacked = stack.get(srcValue); - - if (stacked) { - assignMergeValue(object, key, stacked); - return; - } - var newValue = customizer - ? customizer(objValue, srcValue, (key + ''), object, source, stack) - : undefined; - - var isCommon = newValue === undefined; - - if (isCommon) { - var isArr = isArray(srcValue), - isBuff = !isArr && isBuffer(srcValue), - isTyped = !isArr && !isBuff && isTypedArray(srcValue); - - newValue = srcValue; - if (isArr || isBuff || isTyped) { - if (isArray(objValue)) { - newValue = objValue; - } - else if (isArrayLikeObject(objValue)) { - newValue = copyArray(objValue); - } - else if (isBuff) { - isCommon = false; - newValue = cloneBuffer(srcValue, true); - } - else if (isTyped) { - isCommon = false; - newValue = cloneTypedArray(srcValue, true); - } - else { - newValue = []; - } - } - else if (isPlainObject(srcValue) || isArguments(srcValue)) { - newValue = objValue; - if (isArguments(objValue)) { - newValue = toPlainObject(objValue); - } - else if (!isObject(objValue) || isFunction(objValue)) { - newValue = initCloneObject(srcValue); - } - } - else { - isCommon = false; - } - } - if (isCommon) { - // Recursively merge objects and arrays (susceptible to call stack limits). - stack.set(srcValue, newValue); - mergeFunc(newValue, srcValue, srcIndex, customizer, stack); - stack['delete'](srcValue); - } - assignMergeValue(object, key, newValue); +function objHasProp(obj, name) { + var prop = Object.getOwnPropertyDescriptor(obj, name); + return prop !== undefined && prop.value ? prop.value : prop } /** - * The base implementation of `_.merge` without support for multiple sources. - * - * @private - * @param {Object} object The destination object. - * @param {Object} source The source object. - * @param {number} srcIndex The index of `source`. - * @param {Function} [customizer] The function to customize merged values. - * @param {Object} [stack] Tracks traversed source values and their merged - * counterparts. + * After the user login we will use this Object.define add a new property + * to the resolver with the decoded user data + * @param {function} resolver target resolver + * @param {string} name the name of the object to get inject also for checking + * @param {object} data to inject into the function static interface + * @param {boolean} [overwrite=false] if we want to overwrite the existing data + * @return {function} added property resolver */ -function baseMerge(object, source, srcIndex, customizer, stack) { - if (object === source) { - return; +function injectToFn(resolver, name, data, overwrite) { + if ( overwrite === void 0 ) overwrite = false; + + var check = objHasProp(resolver, name); + if (overwrite === false && check !== undefined) { + // console.info(`NOT INJECTED`) + return resolver } - baseFor(source, function(srcValue, key) { - stack || (stack = new Stack); - if (isObject(srcValue)) { - baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); - } - else { - var newValue = customizer - ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack) - : undefined; + /* this will throw error! @TODO how to remove props? + if (overwrite === true && check !== undefined) { + delete resolver[name] // delete this property + } + */ + // console.info(`INJECTED`) + Object.defineProperty(resolver, name, { + value: data, + writable: overwrite // if its set to true then we should able to overwrite it + }); - if (newValue === undefined) { - newValue = srcValue; - } - assignMergeValue(object, key, newValue); - } - }, keysIn); + return resolver } +var NO_ERROR_MSG = 'No message'; +var NO_STATUS_CODE = -1; +var UNAUTHORIZED_STATUS = 401; +var FORBIDDEN_STATUS = 403; +var NOT_FOUND_STATUS = 404; +var NOT_ACCEPTABLE_STATUS = 406; +var SERVER_INTERNAL_STATUS = 500; + /** - * This method returns the first argument it receives. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Util - * @param {*} value Any value. - * @returns {*} Returns `value`. - * @example - * - * var object = { 'a': 1 }; - * - * console.log(_.identity(object) === object); - * // => true + * This is a custom error to throw when server throw a 406 + * This help us to capture the right error, due to the call happens in sequence + * @param {string} message to tell what happen + * @param {mixed} extra things we want to add, 500? */ -function identity(value) { - return value; -} +var Jsonql406Error = /*@__PURE__*/(function (Error) { + function Jsonql406Error() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; -/** - * A faster alternative to `Function#apply`, this function invokes `func` - * with the `this` binding of `thisArg` and the arguments of `args`. - * - * @private - * @param {Function} func The function to invoke. - * @param {*} thisArg The `this` binding of `func`. - * @param {Array} args The arguments to invoke `func` with. - * @returns {*} Returns the result of `func`. - */ -function apply(func, thisArg, args) { - switch (args.length) { - case 0: return func.call(thisArg); - case 1: return func.call(thisArg, args[0]); - case 2: return func.call(thisArg, args[0], args[1]); - case 3: return func.call(thisArg, args[0], args[1], args[2]); + Error.apply(this, args); + this.message = args[0]; + this.detail = args[1]; + // We can't access the static name from an instance + // but we can do it like this + this.className = Jsonql406Error.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, Jsonql406Error); + } } - return func.apply(thisArg, args); -} -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeMax = Math.max; + if ( Error ) Jsonql406Error.__proto__ = Error; + Jsonql406Error.prototype = Object.create( Error && Error.prototype ); + Jsonql406Error.prototype.constructor = Jsonql406Error; -/** - * A specialized version of `baseRest` which transforms the rest array. - * - * @private - * @param {Function} func The function to apply a rest parameter to. - * @param {number} [start=func.length-1] The start position of the rest parameter. - * @param {Function} transform The rest array transform. - * @returns {Function} Returns the new function. - */ -function overRest(func, start, transform) { - start = nativeMax(start === undefined ? (func.length - 1) : start, 0); - return function() { - var args = arguments, - index = -1, - length = nativeMax(args.length - start, 0), - array = Array(length); + var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; - while (++index < length) { - array[index] = args[start + index]; - } - index = -1; - var otherArgs = Array(start + 1); - while (++index < start) { - otherArgs[index] = args[index]; - } - otherArgs[start] = transform(array); - return apply(func, this, otherArgs); + staticAccessors.statusCode.get = function () { + return NOT_ACCEPTABLE_STATUS }; -} -/** - * Creates a function that returns `value`. - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Util - * @param {*} value The value to return from the new function. - * @returns {Function} Returns the new constant function. - * @example - * - * var objects = _.times(2, _.constant({ 'a': 1 })); - * - * console.log(objects); - * // => [{ 'a': 1 }, { 'a': 1 }] - * - * console.log(objects[0] === objects[1]); - * // => true - */ -function constant(value) { - return function() { - return value; + staticAccessors.name.get = function () { + return 'Jsonql406Error' }; -} - -/** - * The base implementation of `setToString` without support for hot loop shorting. - * - * @private - * @param {Function} func The function to modify. - * @param {Function} string The `toString` result. - * @returns {Function} Returns `func`. - */ -var baseSetToString = !defineProperty ? identity : function(func, string) { - return defineProperty(func, 'toString', { - 'configurable': true, - 'enumerable': false, - 'value': constant(string), - 'writable': true - }); -}; -/** Used to detect hot functions by number of calls within a span of milliseconds. */ -var HOT_COUNT = 800, - HOT_SPAN = 16; + Object.defineProperties( Jsonql406Error, staticAccessors ); -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeNow = Date.now; + return Jsonql406Error; +}(Error)); /** - * Creates a function that'll short out and invoke `identity` instead - * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` - * milliseconds. - * - * @private - * @param {Function} func The function to restrict. - * @returns {Function} Returns the new shortable function. + * This is a custom error to throw when server throw a 500 + * This help us to capture the right error, due to the call happens in sequence + * @param {string} message to tell what happen + * @param {mixed} extra things we want to add, 500? */ -function shortOut(func) { - var count = 0, - lastCalled = 0; +var Jsonql500Error = /*@__PURE__*/(function (Error) { + function Jsonql500Error() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; - return function() { - var stamp = nativeNow(), - remaining = HOT_SPAN - (stamp - lastCalled); + Error.apply(this, args); - lastCalled = stamp; - if (remaining > 0) { - if (++count >= HOT_COUNT) { - return arguments[0]; - } - } else { - count = 0; + this.message = args[0]; + this.detail = args[1]; + + this.className = Jsonql500Error.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, Jsonql500Error); } - return func.apply(undefined, arguments); + } + + if ( Error ) Jsonql500Error.__proto__ = Error; + Jsonql500Error.prototype = Object.create( Error && Error.prototype ); + Jsonql500Error.prototype.constructor = Jsonql500Error; + + var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; + + staticAccessors.statusCode.get = function () { + return SERVER_INTERNAL_STATUS }; -} -/** - * Sets the `toString` method of `func` to return `string`. - * - * @private - * @param {Function} func The function to modify. - * @param {Function} string The `toString` result. - * @returns {Function} Returns `func`. - */ -var setToString = shortOut(baseSetToString); + staticAccessors.name.get = function () { + return 'Jsonql500Error' + }; -/** - * The base implementation of `_.rest` which doesn't validate or coerce arguments. - * - * @private - * @param {Function} func The function to apply a rest parameter to. - * @param {number} [start=func.length-1] The start position of the rest parameter. - * @returns {Function} Returns the new function. - */ -function baseRest(func, start) { - return setToString(overRest(func, start, identity), func + ''); -} + Object.defineProperties( Jsonql500Error, staticAccessors ); -/** - * Checks if the given arguments are from an iteratee call. - * - * @private - * @param {*} value The potential iteratee value argument. - * @param {*} index The potential iteratee index or key argument. - * @param {*} object The potential iteratee object argument. - * @returns {boolean} Returns `true` if the arguments are from an iteratee call, - * else `false`. - */ -function isIterateeCall(value, index, object) { - if (!isObject(object)) { - return false; - } - var type = typeof index; - if (type == 'number' - ? (isArrayLike$1(object) && isIndex(index, object.length)) - : (type == 'string' && index in object) - ) { - return eq(object[index], value); - } - return false; -} + return Jsonql500Error; +}(Error)); /** - * Creates a function like `_.assign`. - * - * @private - * @param {Function} assigner The function to assign values. - * @returns {Function} Returns the new assigner function. + * this is the 403 Forbidden error + * that means this user is not login + * use the 401 for try to login and failed + * @param {string} message to tell what happen + * @param {mixed} extra things we want to add, 500? */ -function createAssigner(assigner) { - return baseRest(function(object, sources) { - var index = -1, - length = sources.length, - customizer = length > 1 ? sources[length - 1] : undefined, - guard = length > 2 ? sources[2] : undefined; +var JsonqlForbiddenError = /*@__PURE__*/(function (Error) { + function JsonqlForbiddenError() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; - customizer = (assigner.length > 3 && typeof customizer == 'function') - ? (length--, customizer) - : undefined; + Error.apply(this, args); + this.message = args[0]; + this.detail = args[1]; - if (guard && isIterateeCall(sources[0], sources[1], guard)) { - customizer = length < 3 ? undefined : customizer; - length = 1; - } - object = Object(object); - while (++index < length) { - var source = sources[index]; - if (source) { - assigner(object, source, index, customizer); - } + this.className = JsonqlForbiddenError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlForbiddenError); } - return object; - }); -} + } -/** - * This method is like `_.assign` except that it recursively merges own and - * inherited enumerable string keyed properties of source objects into the - * destination object. Source properties that resolve to `undefined` are - * skipped if a destination value exists. Array and plain object properties - * are merged recursively. Other objects and value types are overridden by - * assignment. Source objects are applied from left to right. Subsequent - * sources overwrite property assignments of previous sources. - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 0.5.0 - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @returns {Object} Returns `object`. - * @example - * - * var object = { - * 'a': [{ 'b': 2 }, { 'd': 4 }] - * }; - * - * var other = { - * 'a': [{ 'c': 3 }, { 'e': 5 }] - * }; - * - * _.merge(object, other); - * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } - */ -var merge = createAssigner(function(object, source, srcIndex) { - baseMerge(object, source, srcIndex); -}); + if ( Error ) JsonqlForbiddenError.__proto__ = Error; + JsonqlForbiddenError.prototype = Object.create( Error && Error.prototype ); + JsonqlForbiddenError.prototype.constructor = JsonqlForbiddenError; -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeKeys = overArg(Object.keys, Object); + var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; -/** Used for built-in method references. */ -var objectProto$b = Object.prototype; + staticAccessors.statusCode.get = function () { + return FORBIDDEN_STATUS + }; -/** Used to check objects for own properties. */ -var hasOwnProperty$9 = objectProto$b.hasOwnProperty; + staticAccessors.name.get = function () { + return 'JsonqlForbiddenError'; + }; + + Object.defineProperties( JsonqlForbiddenError, staticAccessors ); + + return JsonqlForbiddenError; +}(Error)); /** - * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. + * This is a custom error to throw when pass credential but fail + * This help us to capture the right error, due to the call happens in sequence + * @param {string} message to tell what happen + * @param {mixed} extra things we want to add, 500? */ -function baseKeys(object) { - if (!isPrototype(object)) { - return nativeKeys(object); - } - var result = []; - for (var key in Object(object)) { - if (hasOwnProperty$9.call(object, key) && key != 'constructor') { - result.push(key); +var JsonqlAuthorisationError = /*@__PURE__*/(function (Error) { + function JsonqlAuthorisationError() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + Error.apply(this, args); + this.message = args[0]; + this.detail = args[1]; + + this.className = JsonqlAuthorisationError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlAuthorisationError); } } - return result; -} -/** - * Creates an array of the own enumerable property names of `object`. - * - * **Note:** Non-object values are coerced to objects. See the - * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) - * for more details. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.keys(new Foo); - * // => ['a', 'b'] (iteration order is not guaranteed) - * - * _.keys('hi'); - * // => ['0', '1'] - */ -function keys(object) { - return isArrayLike$1(object) ? arrayLikeKeys(object) : baseKeys(object); -} + if ( Error ) JsonqlAuthorisationError.__proto__ = Error; + JsonqlAuthorisationError.prototype = Object.create( Error && Error.prototype ); + JsonqlAuthorisationError.prototype.constructor = JsonqlAuthorisationError; -/** - * The base implementation of `_.forOwn` without support for iteratee shorthands. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Object} Returns `object`. - */ -function baseForOwn(object, iteratee) { - return object && baseFor(object, iteratee, keys); -} + var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; -/** Used to stand-in for `undefined` hash values. */ -var HASH_UNDEFINED$2 = '__lodash_hash_undefined__'; + staticAccessors.statusCode.get = function () { + return UNAUTHORIZED_STATUS + }; -/** - * Adds `value` to the array cache. - * - * @private - * @name add - * @memberOf SetCache - * @alias push - * @param {*} value The value to cache. - * @returns {Object} Returns the cache instance. - */ -function setCacheAdd(value) { - this.__data__.set(value, HASH_UNDEFINED$2); - return this; -} + staticAccessors.name.get = function () { + return 'JsonqlAuthorisationError'; + }; -/** - * Checks if `value` is in the array cache. - * - * @private - * @name has - * @memberOf SetCache - * @param {*} value The value to search for. - * @returns {number} Returns `true` if `value` is found, else `false`. - */ -function setCacheHas(value) { - return this.__data__.has(value); -} + Object.defineProperties( JsonqlAuthorisationError, staticAccessors ); + + return JsonqlAuthorisationError; +}(Error)); /** - * - * Creates an array cache object to store unique values. - * - * @private - * @constructor - * @param {Array} [values] The values to cache. + * This is a custom error when not supply the credential and try to get contract + * This help us to capture the right error, due to the call happens in sequence + * @param {string} message to tell what happen + * @param {mixed} extra things we want to add, 500? */ -function SetCache(values) { - var index = -1, - length = values == null ? 0 : values.length; - - this.__data__ = new MapCache; - while (++index < length) { - this.add(values[index]); - } -} +var JsonqlContractAuthError = /*@__PURE__*/(function (Error) { + function JsonqlContractAuthError() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; -// Add methods to `SetCache`. -SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; -SetCache.prototype.has = setCacheHas; + Error.apply(this, args); + this.message = args[0]; + this.detail = args[1]; -/** - * A specialized version of `_.some` for arrays without support for iteratee - * shorthands. - * - * @private - * @param {Array} [array] The array to iterate over. - * @param {Function} predicate The function invoked per iteration. - * @returns {boolean} Returns `true` if any element passes the predicate check, - * else `false`. - */ -function arraySome(array, predicate) { - var index = -1, - length = array == null ? 0 : array.length; + this.className = JsonqlContractAuthError.name; - while (++index < length) { - if (predicate(array[index], index, array)) { - return true; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlContractAuthError); } } - return false; -} + + if ( Error ) JsonqlContractAuthError.__proto__ = Error; + JsonqlContractAuthError.prototype = Object.create( Error && Error.prototype ); + JsonqlContractAuthError.prototype.constructor = JsonqlContractAuthError; + + var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; + + staticAccessors.statusCode.get = function () { + return UNAUTHORIZED_STATUS + }; + + staticAccessors.name.get = function () { + return 'JsonqlContractAuthError' + }; + + Object.defineProperties( JsonqlContractAuthError, staticAccessors ); + + return JsonqlContractAuthError; +}(Error)); /** - * Checks if a `cache` value for `key` exists. - * - * @private - * @param {Object} cache The cache to query. - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + * This is a custom error to throw when the resolver throw error and capture inside the middleware + * This help us to capture the right error, due to the call happens in sequence + * @param {string} message to tell what happen + * @param {mixed} extra things we want to add, 500? */ -function cacheHas(cache, key) { - return cache.has(key); -} +var JsonqlResolverAppError = /*@__PURE__*/(function (Error) { + function JsonqlResolverAppError() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; -/** Used to compose bitmasks for value comparisons. */ -var COMPARE_PARTIAL_FLAG = 1, - COMPARE_UNORDERED_FLAG = 2; + Error.apply(this, args); -/** - * A specialized version of `baseIsEqualDeep` for arrays with support for - * partial deep comparisons. - * - * @private - * @param {Array} array The array to compare. - * @param {Array} other The other array to compare. - * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. - * @param {Function} customizer The function to customize comparisons. - * @param {Function} equalFunc The function to determine equivalents of values. - * @param {Object} stack Tracks traversed `array` and `other` objects. - * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. - */ -function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { - var isPartial = bitmask & COMPARE_PARTIAL_FLAG, - arrLength = array.length, - othLength = other.length; + this.message = args[0]; + this.detail = args[1]; - if (arrLength != othLength && !(isPartial && othLength > arrLength)) { - return false; - } - // Assume cyclic values are equal. - var stacked = stack.get(array); - if (stacked && stack.get(other)) { - return stacked == other; + this.className = JsonqlResolverAppError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlResolverAppError); + } } - var index = -1, - result = true, - seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; - stack.set(array, other); - stack.set(other, array); + if ( Error ) JsonqlResolverAppError.__proto__ = Error; + JsonqlResolverAppError.prototype = Object.create( Error && Error.prototype ); + JsonqlResolverAppError.prototype.constructor = JsonqlResolverAppError; - // Ignore non-index properties. - while (++index < arrLength) { - var arrValue = array[index], - othValue = other[index]; + var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; - if (customizer) { - var compared = isPartial - ? customizer(othValue, arrValue, index, other, array, stack) - : customizer(arrValue, othValue, index, array, other, stack); - } - if (compared !== undefined) { - if (compared) { - continue; - } - result = false; - break; - } - // Recursively compare arrays (susceptible to call stack limits). - if (seen) { - if (!arraySome(other, function(othValue, othIndex) { - if (!cacheHas(seen, othIndex) && - (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { - return seen.push(othIndex); - } - })) { - result = false; - break; - } - } else if (!( - arrValue === othValue || - equalFunc(arrValue, othValue, bitmask, customizer, stack) - )) { - result = false; - break; - } - } - stack['delete'](array); - stack['delete'](other); - return result; -} + staticAccessors.statusCode.get = function () { + return SERVER_INTERNAL_STATUS + }; -/** - * Converts `map` to its key-value pairs. - * - * @private - * @param {Object} map The map to convert. - * @returns {Array} Returns the key-value pairs. - */ -function mapToArray(map) { - var index = -1, - result = Array(map.size); + staticAccessors.name.get = function () { + return 'JsonqlResolverAppError' + }; - map.forEach(function(value, key) { - result[++index] = [key, value]; - }); - return result; -} + Object.defineProperties( JsonqlResolverAppError, staticAccessors ); + + return JsonqlResolverAppError; +}(Error)); /** - * Converts `set` to an array of its values. - * - * @private - * @param {Object} set The set to convert. - * @returns {Array} Returns the values. + * This is a custom error to throw when could not find the resolver + * This help us to capture the right error, due to the call happens in sequence + * @param {string} message to tell what happen + * @param {mixed} extra things we want to add, 500? */ -function setToArray(set) { - var index = -1, - result = Array(set.size); +var JsonqlResolverNotFoundError = /*@__PURE__*/(function (Error) { + function JsonqlResolverNotFoundError() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; - set.forEach(function(value) { - result[++index] = value; - }); - return result; -} + Error.apply(this, args); -/** Used to compose bitmasks for value comparisons. */ -var COMPARE_PARTIAL_FLAG$1 = 1, - COMPARE_UNORDERED_FLAG$1 = 2; + this.message = args[0]; + this.detail = args[1]; -/** `Object#toString` result references. */ -var boolTag$1 = '[object Boolean]', - dateTag$1 = '[object Date]', - errorTag$1 = '[object Error]', - mapTag$1 = '[object Map]', - numberTag$2 = '[object Number]', - regexpTag$1 = '[object RegExp]', - setTag$1 = '[object Set]', - stringTag$2 = '[object String]', - symbolTag$1 = '[object Symbol]'; + this.className = JsonqlResolverNotFoundError.name; -var arrayBufferTag$1 = '[object ArrayBuffer]', - dataViewTag$1 = '[object DataView]'; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlResolverNotFoundError); + } + } -/** Used to convert symbols to primitives and strings. */ -var symbolProto$1 = Symbol ? Symbol.prototype : undefined, - symbolValueOf = symbolProto$1 ? symbolProto$1.valueOf : undefined; + if ( Error ) JsonqlResolverNotFoundError.__proto__ = Error; + JsonqlResolverNotFoundError.prototype = Object.create( Error && Error.prototype ); + JsonqlResolverNotFoundError.prototype.constructor = JsonqlResolverNotFoundError; -/** - * A specialized version of `baseIsEqualDeep` for comparing objects of - * the same `toStringTag`. - * - * **Note:** This function only supports comparing values with tags of - * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. - * - * @private - * @param {Object} object The object to compare. - * @param {Object} other The other object to compare. - * @param {string} tag The `toStringTag` of the objects to compare. - * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. - * @param {Function} customizer The function to customize comparisons. - * @param {Function} equalFunc The function to determine equivalents of values. - * @param {Object} stack Tracks traversed `object` and `other` objects. - * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. - */ -function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { - switch (tag) { - case dataViewTag$1: - if ((object.byteLength != other.byteLength) || - (object.byteOffset != other.byteOffset)) { - return false; - } - object = object.buffer; - other = other.buffer; + var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; - case arrayBufferTag$1: - if ((object.byteLength != other.byteLength) || - !equalFunc(new Uint8Array(object), new Uint8Array(other))) { - return false; - } - return true; + staticAccessors.statusCode.get = function () { + return NOT_FOUND_STATUS + }; - case boolTag$1: - case dateTag$1: - case numberTag$2: - // Coerce booleans to `1` or `0` and dates to milliseconds. - // Invalid dates are coerced to `NaN`. - return eq(+object, +other); + staticAccessors.name.get = function () { + return 'JsonqlResolverNotFoundError'; + }; - case errorTag$1: - return object.name == other.name && object.message == other.message; + Object.defineProperties( JsonqlResolverNotFoundError, staticAccessors ); - case regexpTag$1: - case stringTag$2: - // Coerce regexes to strings and treat strings, primitives and objects, - // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring - // for more details. - return object == (other + ''); + return JsonqlResolverNotFoundError; +}(Error)); - case mapTag$1: - var convert = mapToArray; +// this get throw from within the checkOptions when run through the enum failed +var JsonqlEnumError = /*@__PURE__*/(function (Error) { + function JsonqlEnumError() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; - case setTag$1: - var isPartial = bitmask & COMPARE_PARTIAL_FLAG$1; - convert || (convert = setToArray); + Error.apply(this, args); - if (object.size != other.size && !isPartial) { - return false; - } - // Assume cyclic values are equal. - var stacked = stack.get(object); - if (stacked) { - return stacked == other; - } - bitmask |= COMPARE_UNORDERED_FLAG$1; + this.message = args[0]; + this.detail = args[1]; - // Recursively compare objects (susceptible to call stack limits). - stack.set(object, other); - var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); - stack['delete'](object); - return result; + this.className = JsonqlEnumError.name; - case symbolTag$1: - if (symbolValueOf) { - return symbolValueOf.call(object) == symbolValueOf.call(other); - } + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlEnumError); + } } - return false; -} -/** - * Appends the elements of `values` to `array`. - * - * @private - * @param {Array} array The array to modify. - * @param {Array} values The values to append. - * @returns {Array} Returns `array`. - */ -function arrayPush(array, values) { - var index = -1, - length = values.length, - offset = array.length; + if ( Error ) JsonqlEnumError.__proto__ = Error; + JsonqlEnumError.prototype = Object.create( Error && Error.prototype ); + JsonqlEnumError.prototype.constructor = JsonqlEnumError; - while (++index < length) { - array[offset + index] = values[index]; - } - return array; -} + var staticAccessors = { name: { configurable: true } }; -/** - * The base implementation of `getAllKeys` and `getAllKeysIn` which uses - * `keysFunc` and `symbolsFunc` to get the enumerable property names and - * symbols of `object`. - * - * @private - * @param {Object} object The object to query. - * @param {Function} keysFunc The function to get the keys of `object`. - * @param {Function} symbolsFunc The function to get the symbols of `object`. - * @returns {Array} Returns the array of property names and symbols. - */ -function baseGetAllKeys(object, keysFunc, symbolsFunc) { - var result = keysFunc(object); - return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); -} + staticAccessors.name.get = function () { + return 'JsonqlEnumError' + }; -/** - * A specialized version of `_.filter` for arrays without support for - * iteratee shorthands. - * - * @private - * @param {Array} [array] The array to iterate over. - * @param {Function} predicate The function invoked per iteration. - * @returns {Array} Returns the new filtered array. - */ -function arrayFilter(array, predicate) { - var index = -1, - length = array == null ? 0 : array.length, - resIndex = 0, - result = []; + Object.defineProperties( JsonqlEnumError, staticAccessors ); - while (++index < length) { - var value = array[index]; - if (predicate(value, index, array)) { - result[resIndex++] = value; - } - } - return result; -} + return JsonqlEnumError; +}(Error)); -/** - * This method returns a new empty array. - * - * @static - * @memberOf _ - * @since 4.13.0 - * @category Util - * @returns {Array} Returns the new empty array. - * @example - * - * var arrays = _.times(2, _.stubArray); - * - * console.log(arrays); - * // => [[], []] - * - * console.log(arrays[0] === arrays[1]); - * // => false - */ -function stubArray() { - return []; -} +// this will throw from inside the checkOptions +var JsonqlTypeError = /*@__PURE__*/(function (Error) { + function JsonqlTypeError() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; -/** Used for built-in method references. */ -var objectProto$c = Object.prototype; + Error.apply(this, args); -/** Built-in value references. */ -var propertyIsEnumerable$1 = objectProto$c.propertyIsEnumerable; + this.message = args[0]; + this.detail = args[1]; -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeGetSymbols = Object.getOwnPropertySymbols; + this.className = JsonqlTypeError.name; -/** - * Creates an array of the own enumerable symbols of `object`. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of symbols. - */ -var getSymbols = !nativeGetSymbols ? stubArray : function(object) { - if (object == null) { - return []; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlTypeError); + } } - object = Object(object); - return arrayFilter(nativeGetSymbols(object), function(symbol) { - return propertyIsEnumerable$1.call(object, symbol); - }); -}; -/** - * Creates an array of own enumerable property names and symbols of `object`. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names and symbols. - */ -function getAllKeys(object) { - return baseGetAllKeys(object, keys, getSymbols); -} + if ( Error ) JsonqlTypeError.__proto__ = Error; + JsonqlTypeError.prototype = Object.create( Error && Error.prototype ); + JsonqlTypeError.prototype.constructor = JsonqlTypeError; -/** Used to compose bitmasks for value comparisons. */ -var COMPARE_PARTIAL_FLAG$2 = 1; + var staticAccessors = { name: { configurable: true } }; -/** Used for built-in method references. */ -var objectProto$d = Object.prototype; + staticAccessors.name.get = function () { + return 'JsonqlTypeError' + }; -/** Used to check objects for own properties. */ -var hasOwnProperty$a = objectProto$d.hasOwnProperty; + Object.defineProperties( JsonqlTypeError, staticAccessors ); -/** - * A specialized version of `baseIsEqualDeep` for objects with support for - * partial deep comparisons. - * - * @private - * @param {Object} object The object to compare. - * @param {Object} other The other object to compare. - * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. - * @param {Function} customizer The function to customize comparisons. - * @param {Function} equalFunc The function to determine equivalents of values. - * @param {Object} stack Tracks traversed `object` and `other` objects. - * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. - */ -function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { - var isPartial = bitmask & COMPARE_PARTIAL_FLAG$2, - objProps = getAllKeys(object), - objLength = objProps.length, - othProps = getAllKeys(other), - othLength = othProps.length; + return JsonqlTypeError; +}(Error)); - if (objLength != othLength && !isPartial) { - return false; - } - var index = objLength; - while (index--) { - var key = objProps[index]; - if (!(isPartial ? key in other : hasOwnProperty$a.call(other, key))) { - return false; - } - } - // Assume cyclic values are equal. - var stacked = stack.get(object); - if (stacked && stack.get(other)) { - return stacked == other; - } - var result = true; - stack.set(object, other); - stack.set(other, object); +// allow supply a custom checker function +// if that failed then we throw this error +var JsonqlCheckerError = /*@__PURE__*/(function (Error) { + function JsonqlCheckerError() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; - var skipCtor = isPartial; - while (++index < objLength) { - key = objProps[index]; - var objValue = object[key], - othValue = other[key]; + Error.apply(this, args); + this.message = args[0]; + this.detail = args[1]; - if (customizer) { - var compared = isPartial - ? customizer(othValue, objValue, key, other, object, stack) - : customizer(objValue, othValue, key, object, other, stack); - } - // Recursively compare objects (susceptible to call stack limits). - if (!(compared === undefined - ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) - : compared - )) { - result = false; - break; - } - skipCtor || (skipCtor = key == 'constructor'); - } - if (result && !skipCtor) { - var objCtor = object.constructor, - othCtor = other.constructor; + this.className = JsonqlCheckerError.name; - // Non `Object` object instances with different constructors are not equal. - if (objCtor != othCtor && - ('constructor' in object && 'constructor' in other) && - !(typeof objCtor == 'function' && objCtor instanceof objCtor && - typeof othCtor == 'function' && othCtor instanceof othCtor)) { - result = false; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlCheckerError); } } - stack['delete'](object); - stack['delete'](other); - return result; -} -/* Built-in method references that are verified to be native. */ -var DataView = getNative(root, 'DataView'); + if ( Error ) JsonqlCheckerError.__proto__ = Error; + JsonqlCheckerError.prototype = Object.create( Error && Error.prototype ); + JsonqlCheckerError.prototype.constructor = JsonqlCheckerError; -/* Built-in method references that are verified to be native. */ -var Promise$1 = getNative(root, 'Promise'); + var staticAccessors = { name: { configurable: true } }; -/* Built-in method references that are verified to be native. */ -var Set$1 = getNative(root, 'Set'); + staticAccessors.name.get = function () { + return 'JsonqlCheckerError' + }; -/* Built-in method references that are verified to be native. */ -var WeakMap$1 = getNative(root, 'WeakMap'); + Object.defineProperties( JsonqlCheckerError, staticAccessors ); -/** `Object#toString` result references. */ -var mapTag$2 = '[object Map]', - objectTag$2 = '[object Object]', - promiseTag = '[object Promise]', - setTag$2 = '[object Set]', - weakMapTag$1 = '[object WeakMap]'; + return JsonqlCheckerError; +}(Error)); -var dataViewTag$2 = '[object DataView]'; +// custom validation error class +// when validaton failed +var JsonqlValidationError = /*@__PURE__*/(function (Error) { + function JsonqlValidationError() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; -/** Used to detect maps, sets, and weakmaps. */ -var dataViewCtorString = toSource(DataView), - mapCtorString = toSource(Map$1), - promiseCtorString = toSource(Promise$1), - setCtorString = toSource(Set$1), - weakMapCtorString = toSource(WeakMap$1); + Error.apply(this, args); -/** - * Gets the `toStringTag` of `value`. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ -var getTag = baseGetTag; + this.message = args[0]; + this.detail = args[1]; -// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. -if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag$2) || - (Map$1 && getTag(new Map$1) != mapTag$2) || - (Promise$1 && getTag(Promise$1.resolve()) != promiseTag) || - (Set$1 && getTag(new Set$1) != setTag$2) || - (WeakMap$1 && getTag(new WeakMap$1) != weakMapTag$1)) { - getTag = function(value) { - var result = baseGetTag(value), - Ctor = result == objectTag$2 ? value.constructor : undefined, - ctorString = Ctor ? toSource(Ctor) : ''; + this.className = JsonqlValidationError.name; - if (ctorString) { - switch (ctorString) { - case dataViewCtorString: return dataViewTag$2; - case mapCtorString: return mapTag$2; - case promiseCtorString: return promiseTag; - case setCtorString: return setTag$2; - case weakMapCtorString: return weakMapTag$1; - } + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlValidationError); } - return result; - }; -} + } -var getTag$1 = getTag; + if ( Error ) JsonqlValidationError.__proto__ = Error; + JsonqlValidationError.prototype = Object.create( Error && Error.prototype ); + JsonqlValidationError.prototype.constructor = JsonqlValidationError; -/** Used to compose bitmasks for value comparisons. */ -var COMPARE_PARTIAL_FLAG$3 = 1; + var staticAccessors = { name: { configurable: true } }; -/** `Object#toString` result references. */ -var argsTag$2 = '[object Arguments]', - arrayTag$1 = '[object Array]', - objectTag$3 = '[object Object]'; + staticAccessors.name.get = function () { + return 'JsonqlValidationError' + }; -/** Used for built-in method references. */ -var objectProto$e = Object.prototype; + Object.defineProperties( JsonqlValidationError, staticAccessors ); -/** Used to check objects for own properties. */ -var hasOwnProperty$b = objectProto$e.hasOwnProperty; + return JsonqlValidationError; +}(Error)); /** - * A specialized version of `baseIsEqual` for arrays and objects which performs - * deep comparisons and tracks traversed objects enabling objects with circular - * references to be compared. - * - * @private - * @param {Object} object The object to compare. - * @param {Object} other The other object to compare. - * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. - * @param {Function} customizer The function to customize comparisons. - * @param {Function} equalFunc The function to determine equivalents of values. - * @param {Object} [stack] Tracks traversed `object` and `other` objects. - * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + * This is a custom error to throw whenever a error happen inside the jsonql + * This help us to capture the right error, due to the call happens in sequence + * @param {string} message to tell what happen + * @param {mixed} extra things we want to add, 500? */ -function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { - var objIsArr = isArray(object), - othIsArr = isArray(other), - objTag = objIsArr ? arrayTag$1 : getTag$1(object), - othTag = othIsArr ? arrayTag$1 : getTag$1(other); +var JsonqlError$1 = /*@__PURE__*/(function (Error) { + function JsonqlError() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; - objTag = objTag == argsTag$2 ? objectTag$3 : objTag; - othTag = othTag == argsTag$2 ? objectTag$3 : othTag; + Error.apply(this, args); - var objIsObj = objTag == objectTag$3, - othIsObj = othTag == objectTag$3, - isSameTag = objTag == othTag; + this.message = args[0]; + this.detail = args[1]; - if (isSameTag && isBuffer(object)) { - if (!isBuffer(other)) { - return false; + this.className = JsonqlError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlError); + // this.detail = this.stack; } - objIsArr = true; - objIsObj = false; } - if (isSameTag && !objIsObj) { - stack || (stack = new Stack); - return (objIsArr || isTypedArray(object)) - ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) - : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); - } - if (!(bitmask & COMPARE_PARTIAL_FLAG$3)) { - var objIsWrapped = objIsObj && hasOwnProperty$b.call(object, '__wrapped__'), - othIsWrapped = othIsObj && hasOwnProperty$b.call(other, '__wrapped__'); - if (objIsWrapped || othIsWrapped) { - var objUnwrapped = objIsWrapped ? object.value() : object, - othUnwrapped = othIsWrapped ? other.value() : other; + if ( Error ) JsonqlError.__proto__ = Error; + JsonqlError.prototype = Object.create( Error && Error.prototype ); + JsonqlError.prototype.constructor = JsonqlError; - stack || (stack = new Stack); - return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); - } - } - if (!isSameTag) { - return false; - } - stack || (stack = new Stack); - return equalObjects(object, other, bitmask, customizer, equalFunc, stack); -} + var staticAccessors = { name: { configurable: true },statusCode: { configurable: true } }; -/** - * The base implementation of `_.isEqual` which supports partial comparisons - * and tracks traversed objects. - * - * @private - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @param {boolean} bitmask The bitmask flags. - * 1 - Unordered comparison - * 2 - Partial comparison - * @param {Function} [customizer] The function to customize comparisons. - * @param {Object} [stack] Tracks traversed `value` and `other` objects. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - */ -function baseIsEqual(value, other, bitmask, customizer, stack) { - if (value === other) { - return true; - } - if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { - return value !== value && other !== other; - } - return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); -} + staticAccessors.name.get = function () { + return 'JsonqlError' + }; -/** Used to compose bitmasks for value comparisons. */ -var COMPARE_PARTIAL_FLAG$4 = 1, - COMPARE_UNORDERED_FLAG$2 = 2; + staticAccessors.statusCode.get = function () { + return NO_STATUS_CODE + }; -/** - * The base implementation of `_.isMatch` without support for iteratee shorthands. - * - * @private - * @param {Object} object The object to inspect. - * @param {Object} source The object of property values to match. - * @param {Array} matchData The property names, values, and compare flags to match. - * @param {Function} [customizer] The function to customize comparisons. - * @returns {boolean} Returns `true` if `object` is a match, else `false`. - */ -function baseIsMatch(object, source, matchData, customizer) { - var index = matchData.length, - length = index, - noCustomizer = !customizer; + Object.defineProperties( JsonqlError, staticAccessors ); - if (object == null) { - return !length; - } - object = Object(object); - while (index--) { - var data = matchData[index]; - if ((noCustomizer && data[2]) - ? data[1] !== object[data[0]] - : !(data[0] in object) - ) { - return false; - } - } - while (++index < length) { - data = matchData[index]; - var key = data[0], - objValue = object[key], - srcValue = data[1]; + return JsonqlError; +}(Error)); - if (noCustomizer && data[2]) { - if (objValue === undefined && !(key in object)) { - return false; - } - } else { - var stack = new Stack; - if (customizer) { - var result = customizer(objValue, srcValue, key, object, source, stack); - } - if (!(result === undefined - ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG$4 | COMPARE_UNORDERED_FLAG$2, customizer, stack) - : result - )) { - return false; - } - } +// this is from an example from Koa team to use for internal middleware ctx.throw +// but after the test the res.body part is unable to extract the required data +// I keep this one here for future reference + +var JsonqlServerError = /*@__PURE__*/(function (Error) { + function JsonqlServerError(statusCode, message) { + Error.call(this, message); + this.statusCode = statusCode; + this.className = JsonqlServerError.name; } - return true; -} -/** - * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` if suitable for strict - * equality comparisons, else `false`. - */ -function isStrictComparable(value) { - return value === value && !isObject(value); -} + if ( Error ) JsonqlServerError.__proto__ = Error; + JsonqlServerError.prototype = Object.create( Error && Error.prototype ); + JsonqlServerError.prototype.constructor = JsonqlServerError; -/** - * Gets the property names, values, and compare flags of `object`. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the match data of `object`. - */ -function getMatchData(object) { - var result = keys(object), - length = result.length; + var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; - while (length--) { - var key = result[length], - value = object[key]; + staticAccessors.statusCode.get = function () { + return SERVER_INTERNAL_STATUS + }; - result[length] = [key, value, isStrictComparable(value)]; - } - return result; -} + staticAccessors.name.get = function () { + return 'JsonqlServerError' + }; -/** - * A specialized version of `matchesProperty` for source values suitable - * for strict equality comparisons, i.e. `===`. - * - * @private - * @param {string} key The key of the property to get. - * @param {*} srcValue The value to match. - * @returns {Function} Returns the new spec function. + Object.defineProperties( JsonqlServerError, staticAccessors ); + + return JsonqlServerError; +}(Error)); + +/** + * this will put into generator call at the very end and catch + * the error throw from inside then throw again + * this is necessary because we split calls inside and the throw + * will not reach the actual client unless we do it this way + * @param {object} e Error + * @return {void} just throw */ -function matchesStrictComparable(key, srcValue) { - return function(object) { - if (object == null) { - return false; - } - return object[key] === srcValue && - (srcValue !== undefined || (key in Object(object))); - }; +function finalCatch(e) { + // this is a hack to get around the validateAsync not actually throw error + // instead it just rejected it with the array of failed parameters + if (Array.isArray(e)) { + // if we want the message then I will have to create yet another function + // to wrap this function to provide the name prop + throw new JsonqlValidationError('', e) + } + var msg = e.message || NO_ERROR_MSG; + var detail = e.detail || e; + // @BUG the instance of not always work for some reason! + // need to figure out a better way to find out the type of the error + switch (true) { + case e instanceof Jsonql406Error: + throw new Jsonql406Error(msg, detail) + case e instanceof Jsonql500Error: + throw new Jsonql500Error(msg, detail) + case e instanceof JsonqlForbiddenError: + throw new JsonqlForbiddenError(msg, detail) + case e instanceof JsonqlAuthorisationError: + throw new JsonqlAuthorisationError(msg, detail) + case e instanceof JsonqlContractAuthError: + throw new JsonqlContractAuthError(msg, detail) + case e instanceof JsonqlResolverAppError: + throw new JsonqlResolverAppError(msg, detail) + case e instanceof JsonqlResolverNotFoundError: + throw new JsonqlResolverNotFoundError(msg, detail) + case e instanceof JsonqlEnumError: + throw new JsonqlEnumError(msg, detail) + case e instanceof JsonqlTypeError: + throw new JsonqlTypeError(msg, detail) + case e instanceof JsonqlCheckerError: + throw new JsonqlCheckerError(msg, detail) + case e instanceof JsonqlValidationError: + throw new JsonqlValidationError(msg, detail) + case e instanceof JsonqlServerError: + throw new JsonqlServerError(msg, detail) + default: + throw new JsonqlError$1(msg, detail) + } } +// split the contract into the node side and the generic side /** - * The base implementation of `_.matches` which doesn't clone `source`. - * - * @private - * @param {Object} source The object of property values to match. - * @returns {Function} Returns the new spec function. + * Check if the json is a contract file or not + * @param {object} contract json object + * @return {boolean} true */ -function baseMatches(source) { - var matchData = getMatchData(source); - if (matchData.length == 1 && matchData[0][2]) { - return matchesStrictComparable(matchData[0][0], matchData[0][1]); - } - return function(object) { - return object === source || baseIsMatch(object, source, matchData); - }; +function checkIsContract(contract) { + return isPlainObject(contract) + && ( + isObjectHasKey(contract, QUERY_NAME) + || isObjectHasKey(contract, MUTATION_NAME) + || isObjectHasKey(contract, SOCKET_NAME) + ) } -/** Used to match property names within property paths. */ -var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, - reIsPlainProp = /^\w*$/; +/** + * Wrapper method that check if it's contract then return the contract or false + * @param {object} contract the object to check + * @return {boolean | object} false when it's not + */ +function isContract(contract) { + return checkIsContract(contract) ? contract : false +} /** - * Checks if `value` is a property name and not a property path. - * - * @private - * @param {*} value The value to check. - * @param {Object} [object] The object to query keys on. - * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + * Ported from jsonql-params-validator but different + * if we don't find the socket part then return false + * @param {object} contract the contract object + * @return {object|boolean} false on failed */ -function isKey(value, object) { - if (isArray(value)) { - return false; - } - var type = typeof value; - if (type == 'number' || type == 'symbol' || type == 'boolean' || - value == null || isSymbol(value)) { - return true; +function extractSocketPart(contract) { + if (isObjectHasKey(contract, SOCKET_NAME)) { + return contract[SOCKET_NAME] } - return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || - (object != null && value in Object(object)); + return false } -/** Error message constants. */ -var FUNC_ERROR_TEXT = 'Expected a function'; +/** + * @param {boolean} sec return in second or not + * @return {number} timestamp + */ +var timestamp = function (sec) { + if ( sec === void 0 ) sec = false; + + var time = Date.now(); + return sec ? Math.floor( time / 1000 ) : time +}; + +/** `Object#toString` result references. */ +var stringTag$1 = '[object String]'; /** - * Creates a function that memoizes the result of `func`. If `resolver` is - * provided, it determines the cache key for storing the result based on the - * arguments provided to the memoized function. By default, the first argument - * provided to the memoized function is used as the map cache key. The `func` - * is invoked with the `this` binding of the memoized function. - * - * **Note:** The cache is exposed as the `cache` property on the memoized - * function. Its creation may be customized by replacing the `_.memoize.Cache` - * constructor with one whose instances implement the - * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) - * method interface of `clear`, `delete`, `get`, `has`, and `set`. + * Checks if `value` is classified as a `String` primitive or object. * * @static - * @memberOf _ * @since 0.1.0 - * @category Function - * @param {Function} func The function to have its output memoized. - * @param {Function} [resolver] The function to resolve the cache key. - * @returns {Function} Returns the new memoized function. + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. * @example * - * var object = { 'a': 1, 'b': 2 }; - * var other = { 'c': 3, 'd': 4 }; - * - * var values = _.memoize(_.values); - * values(object); - * // => [1, 2] - * - * values(other); - * // => [3, 4] - * - * object.a = 2; - * values(object); - * // => [1, 2] - * - * // Modify the result cache. - * values.cache.set(object, ['a', 'b']); - * values(object); - * // => ['a', 'b'] + * _.isString('abc'); + * // => true * - * // Replace `_.memoize.Cache`. - * _.memoize.Cache = WeakMap; + * _.isString(1); + * // => false */ -function memoize(func, resolver) { - if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) { - throw new TypeError(FUNC_ERROR_TEXT); - } - var memoized = function() { - var args = arguments, - key = resolver ? resolver.apply(this, args) : args[0], - cache = memoized.cache; - - if (cache.has(key)) { - return cache.get(key); - } - var result = func.apply(this, args); - memoized.cache = cache.set(key, result) || cache; - return result; - }; - memoized.cache = new (memoize.Cache || MapCache); - return memoized; +function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag$1); } -// Expose `MapCache`. -memoize.Cache = MapCache; - -/** Used as the maximum memoize cache size. */ -var MAX_MEMOIZE_SIZE = 500; +// ported from jsonql-params-validator /** - * A specialized version of `_.memoize` which clears the memoized function's - * cache when it exceeds `MAX_MEMOIZE_SIZE`. - * - * @private - * @param {Function} func The function to have its output memoized. - * @returns {Function} Returns the new memoized function. + * @param {*} args arguments to send + *@return {object} formatted payload */ -function memoizeCapped(func) { - var result = memoize(func, function(key) { - if (cache.size === MAX_MEMOIZE_SIZE) { - cache.clear(); - } - return key; - }); +var formatPayload = function (args) { + var obj; - var cache = result.cache; - return result; -} + return ( + ( obj = {}, obj[QUERY_ARG_NAME] = args, obj ) +); +}; -/** Used to match property names within property paths. */ -var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; +/** + * wrapper method to add the timestamp as well + * @param {string} resolverName + * @param {*} payload + * @return {object} delierable + */ +function createDeliverable(resolverName, payload) { + var obj; -/** Used to match backslashes in property paths. */ -var reEscapeChar = /\\(\\)?/g; + return ( obj = {}, obj[resolverName] = payload, obj[TIMESTAMP_PARAM_NAME] = [ timestamp() ], obj ) +} /** - * Converts `string` to a property path array. - * - * @private - * @param {string} string The string to convert. - * @returns {Array} Returns the property path array. + * @param {string} resolverName name of function + * @param {array} [args=[]] from the ...args + * @param {boolean} [jsonp = false] add v1.3.0 to koa + * @return {object} formatted argument */ -var stringToPath = memoizeCapped(function(string) { - var result = []; - if (string.charCodeAt(0) === 46 /* . */) { - result.push(''); +function createQuery(resolverName, args, jsonp) { + if ( args === void 0 ) args = []; + if ( jsonp === void 0 ) jsonp = false; + + if (isString(resolverName) && isArray(args)) { + var payload = formatPayload(args); + if (jsonp === true) { + return payload + } + return createDeliverable(resolverName, payload) } - string.replace(rePropName, function(match, number, quote, subString) { - result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match)); - }); - return result; -}); + throw new JsonqlValidationError("[createQuery] expect resolverName to be string and args to be array!", { resolverName: resolverName, args: args }) +} /** - * Casts `value` to a path array if it's not one. - * - * @private - * @param {*} value The value to inspect. - * @param {Object} [object] The object to query keys on. - * @returns {Array} Returns the cast property path array. + * string version of the createQuery + * @return {string} */ -function castPath(value, object) { - if (isArray(value)) { - return value; - } - return isKey(value, object) ? [value] : stringToPath(toString(value)); +function createQueryStr(resolverName, args, jsonp) { + if ( args === void 0 ) args = []; + if ( jsonp === void 0 ) jsonp = false; + + return JSON.stringify(createQuery(resolverName, args, jsonp)) } -/** Used as references for various `Number` constants. */ -var INFINITY$1 = 1 / 0; +// take out all the namespace related methods in one place for easy to find +var SOCKET_NOT_FOUND_ERR = "socket not found in contract!"; +var SIZE = 'size'; /** - * Converts `value` to a string key if it's not a string or symbol. - * - * @private - * @param {*} value The value to inspect. - * @returns {string|symbol} Returns the key. + * create the group using publicNamespace when there is only public + * @param {object} socket from contract + * @param {string} publicNamespace */ -function toKey(value) { - if (typeof value == 'string' || isSymbol(value)) { - return value; +function groupPublicNamespace(socket, publicNamespace) { + var obj; + + var g = {}; + for (var resolverName in socket) { + var params = socket[resolverName]; + g[resolverName] = params; } - var result = (value + ''); - return (result == '0' && (1 / value) == -INFINITY$1) ? '-0' : result; + return { size: 1, nspGroup: ( obj = {}, obj[publicNamespace] = g, obj ), publicNamespace: publicNamespace} } + /** - * The base implementation of `_.get` without support for default values. - * - * @private - * @param {Object} object The object to query. - * @param {Array|string} path The path of the property to get. - * @returns {*} Returns the resolved value. + * @BUG we should check the socket part instead of expect the downstream to read the menu! + * We only need this when the enableAuth is true otherwise there is only one namespace + * @param {object} contract the socket part of the contract file + * @return {object} 1. remap the contract using the namespace --> resolvers + * 2. the size of the object (1 all private, 2 mixed public with private) + * 3. which namespace is public */ -function baseGet(object, path) { - path = castPath(path, object); +function groupByNamespace(contract) { + var socket = extractSocketPart(contract); + if (socket === false) { + throw new JsonqlError('groupByNamespace', SOCKET_NOT_FOUND_ERR) + } + var prop = {}; + prop[NSP_GROUP] = {}; + prop[PUBLIC_NAMESPACE] = null; + prop[SIZE] = 0; - var index = 0, - length = path.length; + for (var resolverName in socket) { + var params = socket[resolverName]; + var namespace = params.namespace; + if (namespace) { + if (!prop[NSP_GROUP][namespace]) { + ++prop[SIZE]; + prop[NSP_GROUP][namespace] = {}; + } + prop[NSP_GROUP][namespace][resolverName] = params; + // get the public namespace + if (!prop[PUBLIC_NAMESPACE] && params[PUBLIC_KEY]) { + prop[PUBLIC_NAMESPACE] = namespace; + } + } + } + + return prop +} - while (object != null && index < length) { - object = object[toKey(path[index++])]; +/** + * @TODO this might change, what if we want to do room with ws + * 1. there will only be max two namespace + * 2. when it's normal we will have the stock path as namespace + * 3. when enableAuth then we will have two, one is jsonql/public + private + * @param {object} config options + * @return {array} of namespace(s) + */ +function getNamespace(config) { + var base = JSONQL_PATH; + if (config.enableAuth) { + // the public come first @1.0.1 we use the constants instead of the user supplied value + // @1.0.4 we use the config value again, because we could control this via the post init + return [ + [ base , config.privateNamespace ].join('/'), + [ base , config.publicNamespace ].join('/') + ] } - return (index && index == length) ? object : undefined; + return [ base ] } /** - * Gets the value at `path` of `object`. If the resolved value is - * `undefined`, the `defaultValue` is returned in its place. - * - * @static - * @memberOf _ - * @since 3.7.0 - * @category Object - * @param {Object} object The object to query. - * @param {Array|string} path The path of the property to get. - * @param {*} [defaultValue] The value returned for `undefined` resolved values. - * @returns {*} Returns the resolved value. - * @example - * - * var object = { 'a': [{ 'b': { 'c': 3 } }] }; - * - * _.get(object, 'a[0].b.c'); - * // => 3 - * - * _.get(object, ['a', '0', 'b', 'c']); - * // => 3 - * - * _.get(object, 'a.b.c', 'default'); - * // => 'default' + * get the private namespace + * @param {array} namespaces array + * @return {*} string on success */ -function get(object, path, defaultValue) { - var result = object == null ? undefined : baseGet(object, path); - return result === undefined ? defaultValue : result; +function getPrivateNamespace$1(namespaces) { + return namespaces.length > 1 ? namespaces[0] : false } /** - * The base implementation of `_.hasIn` without support for deep paths. - * - * @private - * @param {Object} [object] The object to query. - * @param {Array|string} key The key to check. - * @returns {boolean} Returns `true` if `key` exists, else `false`. + * Got a problem with a contract that is public only the groupByNamespace is wrong + * which is actually not a problem when using a fallback, but to be sure things in order + * we could combine with the config to group it + * @param {object} config configuration + * @return {object} nspInfo object */ -function baseHasIn(object, key) { - return object != null && key in Object(object); +function getNspInfoByConfig(config) { + var contract = config.contract; + var enableAuth = config.enableAuth; + var namespaces = getNamespace(config); + var nspInfo = enableAuth ? groupByNamespace(contract) + : groupPublicNamespace(contract.socket, namespaces[0]); + // add the namespaces into it as well + return Object.assign(nspInfo, { namespaces: namespaces }) } +// There are the socket related methods ported back from + +var PAYLOAD_NOT_DECODED_ERR = 'payload can not decoded'; +var WS_KEYS = [ + WS_REPLY_TYPE, + WS_EVT_NAME, + WS_DATA_NAME +]; + /** - * Checks if `path` exists on `object`. - * - * @private - * @param {Object} object The object to query. - * @param {Array|string} path The path to check. - * @param {Function} hasFunc The function to check properties. - * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @param {string|object} payload should be string when reply but could be transformed + * @return {boolean} true is OK */ -function hasPath(object, path, hasFunc) { - path = castPath(path, object); +var isWsReply = function (payload) { + var json = isString(payload) ? toJson(payload) : payload; + var data = json.data; + if (data) { + var result = WS_KEYS.filter(function (key) { return isObjectHasKey(data, key); }); + return (result.length === WS_KEYS.length) ? data : false + } + return false +}; - var index = -1, - length = path.length, - result = false; +/** + * @param {string|object} data received data + * @param {function} [cb=nil] this is for extracting the TS field or when it's error + * @return {object} false on failed + */ +var extractWsPayload = function (payload, cb) { + if ( cb === void 0 ) cb = nil; - while (++index < length) { - var key = toKey(path[index]); - if (!(result = object != null && hasFunc(object, key))) { - break; + try { + var json = toJson(payload); + // now handle the data + var _data; + if ((_data = isWsReply(json)) !== false) { + // note the ts property is on its own + cb(TIMESTAMP_PARAM_NAME, json[TIMESTAMP_PARAM_NAME]); + + return { + data: toJson(_data[WS_DATA_NAME]), + resolverName: _data[WS_EVT_NAME], + type: _data[WS_REPLY_TYPE] + } } - object = object[key]; + throw new JsonqlError$1(PAYLOAD_NOT_DECODED_ERR, payload) + } catch(e) { + return cb(ERROR_KEY, e) } - if (result || ++index != length) { - return result; +}; + +// this will be part of the init client sequence +var CSRF_HEADER_NOT_EXIST_ERR = 'CSRF header is not in the received payload'; + +/** + * Util method + * @param {string} payload return from server + * @return {object} the useful bit + */ +function extractSrvPayload(payload) { + var json = toJson(payload); + + if (json && typeof json === 'object') { + // note this method expect the json.data inside + return extractWsPayload(json) } - length = object == null ? 0 : object.length; - return !!length && isLength(length) && isIndex(key, length) && - (isArray(object) || isArguments(object)); + + throw new JsonqlError$1('extractSrvPayload', json) } /** - * Checks if `path` is a direct or inherited property of `object`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Object - * @param {Object} object The object to query. - * @param {Array|string} path The path to check. - * @returns {boolean} Returns `true` if `path` exists, else `false`. - * @example - * - * var object = _.create({ 'a': _.create({ 'b': 2 }) }); - * - * _.hasIn(object, 'a'); - * // => true - * - * _.hasIn(object, 'a.b'); - * // => true - * - * _.hasIn(object, ['a', 'b']); - * // => true - * - * _.hasIn(object, 'b'); - * // => false + * call the server to get a csrf token + * @return {string} formatted payload to send to the server */ -function hasIn(object, path) { - return object != null && hasPath(object, path, baseHasIn); -} +function createInitPing() { + var ts = timestamp(); -/** Used to compose bitmasks for value comparisons. */ -var COMPARE_PARTIAL_FLAG$5 = 1, - COMPARE_UNORDERED_FLAG$3 = 2; + return createQueryStr(INTERCOM_RESOLVER_NAME, [SOCKET_PING_EVENT_NAME, ts]) +} /** - * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. - * - * @private - * @param {string} path The path of the property to get. - * @param {*} srcValue The value to match. - * @returns {Function} Returns the new spec function. + * Take the raw on.message result back then decoded it + * @param {*} payload the raw result from server + * @return {object} the csrf payload */ -function baseMatchesProperty(path, srcValue) { - if (isKey(path) && isStrictComparable(srcValue)) { - return matchesStrictComparable(toKey(path), srcValue); +function extractPingResult(payload) { + var obj; + + var result = extractSrvPayload(payload); + + if (result && result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) { + return ( obj = {}, obj[HEADERS_KEY] = result[DATA_KEY], obj ) } - return function(object) { - var objValue = get(object, path); - return (objValue === undefined && objValue === srcValue) - ? hasIn(object, path) - : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG$5 | COMPARE_UNORDERED_FLAG$3); - }; + + throw new JsonqlError$1('extractPingResult', CSRF_HEADER_NOT_EXIST_ERR) } + /** - * The base implementation of `_.property` without support for deep paths. - * - * @private - * @param {string} key The key of the property to get. - * @returns {Function} Returns the new accessor function. + * Create a generic intercom method + * @param {string} type the event type + * @param {array} args if any + * @return {string} formatted payload to send */ -function baseProperty(key) { - return function(object) { - return object == null ? undefined : object[key]; - }; +function createIntercomPayload(type) { + var args = [], len = arguments.length - 1; + while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; + + var ts = timestamp(); + var payload = [type].concat(args); + payload.push(ts); + return createQueryStr(INTERCOM_RESOLVER_NAME, payload) } /** - * A specialized version of `baseProperty` which supports deep paths. - * - * @private - * @param {Array|string} path The path of the property to get. - * @returns {Function} Returns the new accessor function. + * Check several parameter that there is something in the param + * @param {*} param input + * @return {boolean} */ -function basePropertyDeep(path) { - return function(object) { - return baseGet(object, path); - }; -} + var isNotEmpty = function (a) { + if (isArray(a)) { + return true; + } + return a !== undefined && a !== null && trim(a) !== '' +}; + +/** `Object#toString` result references. */ +var numberTag$1 = '[object Number]'; /** - * Creates a function that returns the value at `path` of a given object. + * Checks if `value` is classified as a `Number` primitive or object. + * + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are + * classified as numbers, use the `_.isFinite` method. * * @static * @memberOf _ - * @since 2.4.0 - * @category Util - * @param {Array|string} path The path of the property to get. - * @returns {Function} Returns the new accessor function. + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a number, else `false`. * @example * - * var objects = [ - * { 'a': { 'b': 2 } }, - * { 'a': { 'b': 1 } } - * ]; + * _.isNumber(3); + * // => true * - * _.map(objects, _.property('a.b')); - * // => [2, 1] + * _.isNumber(Number.MIN_VALUE); + * // => true * - * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b'); - * // => [1, 2] - */ -function property(path) { - return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path); -} - -/** - * The base implementation of `_.iteratee`. + * _.isNumber(Infinity); + * // => true * - * @private - * @param {*} [value=_.identity] The value to convert to an iteratee. - * @returns {Function} Returns the iteratee. + * _.isNumber('3'); + * // => false */ -function baseIteratee(value) { - // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. - // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. - if (typeof value == 'function') { - return value; - } - if (value == null) { - return identity; - } - if (typeof value == 'object') { - return isArray(value) - ? baseMatchesProperty(value[0], value[1]) - : baseMatches(value); - } - return property(value); +function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && baseGetTag(value) == numberTag$1); } /** - * Creates an object with the same keys as `object` and values generated - * by running each own enumerable string keyed property of `object` thru - * `iteratee`. The iteratee is invoked with three arguments: - * (value, key, object). + * Checks if `value` is `NaN`. + * + * **Note:** This method is based on + * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as + * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for + * `undefined` and other non-number values. * * @static * @memberOf _ - * @since 2.4.0 - * @category Object - * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Object} Returns the new mapped object. - * @see _.mapKeys + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. * @example * - * var users = { - * 'fred': { 'user': 'fred', 'age': 40 }, - * 'pebbles': { 'user': 'pebbles', 'age': 1 } - * }; + * _.isNaN(NaN); + * // => true * - * _.mapValues(users, function(o) { return o.age; }); - * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + * _.isNaN(new Number(NaN)); + * // => true * - * // The `_.property` iteratee shorthand. - * _.mapValues(users, 'age'); - * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false */ -function mapValues(object, iteratee) { - var result = {}; - iteratee = baseIteratee(iteratee); - - baseForOwn(object, function(value, key, object) { - baseAssignValue(result, key, iteratee(value, key, object)); - }); - return result; +function isNaN(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. + return isNumber(value) && value != +value; } +// validator numbers /** - * The opposite of `_.mapValues`; this method creates an object with the - * same values as `object` and keys generated by running each own enumerable - * string keyed property of `object` thru `iteratee`. The iteratee is invoked - * with three arguments: (value, key, object). - * - * @static - * @memberOf _ - * @since 3.8.0 - * @category Object - * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Object} Returns the new mapped object. - * @see _.mapValues - * @example - * - * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { - * return key + value; - * }); - * // => { 'a1': 1, 'b2': 2 } + * @2015-05-04 found a problem if the value is a number like string + * it will pass, so add a chck if it's string before we pass to next + * @param {number} value expected value + * @return {boolean} true if OK */ -function mapKeys(object, iteratee) { - var result = {}; - iteratee = baseIteratee(iteratee); +var checkIsNumber = function(value) { + return isString(value) ? false : !isNaN( parseFloat(value) ) +}; - baseForOwn(object, function(value, key, object) { - baseAssignValue(result, iteratee(value, key, object), value); - }); - return result; -} +// validate string type +/** + * @param {string} value expected value + * @return {boolean} true if OK + */ +var checkIsString = function(value) { + return (trim(value) !== '') ? isString(value) : false +}; -/** Error message constants. */ -var FUNC_ERROR_TEXT$1 = 'Expected a function'; +// check for boolean /** - * Creates a function that negates the result of the predicate `func`. The - * `func` predicate is invoked with the `this` binding and arguments of the - * created function. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Function - * @param {Function} predicate The predicate to negate. - * @returns {Function} Returns the new negated function. - * @example - * - * function isEven(n) { - * return n % 2 == 0; - * } - * - * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); - * // => [1, 3, 5] + * @param {boolean} value expected + * @return {boolean} true if OK */ -function negate(predicate) { - if (typeof predicate != 'function') { - throw new TypeError(FUNC_ERROR_TEXT$1); - } - return function() { - var args = arguments; - switch (args.length) { - case 0: return !predicate.call(this); - case 1: return !predicate.call(this, args[0]); - case 2: return !predicate.call(this, args[0], args[1]); - case 3: return !predicate.call(this, args[0], args[1], args[2]); - } - return !predicate.apply(this, args); - }; -} +var checkIsBoolean = function(value) { + return value !== null && value !== undefined && typeof value === 'boolean' +}; + +// validate any thing only check if there is something /** - * The base implementation of `_.set`. - * - * @private - * @param {Object} object The object to modify. - * @param {Array|string} path The path of the property to set. - * @param {*} value The value to set. - * @param {Function} [customizer] The function to customize path creation. - * @returns {Object} Returns `object`. + * @param {*} value the value + * @param {boolean} [checkNull=true] strict check if there is null value + * @return {boolean} true is OK */ -function baseSet(object, path, value, customizer) { - if (!isObject(object)) { - return object; +var checkIsAny = function(value, checkNull) { + if ( checkNull === void 0 ) checkNull = true; + + if (value !== undefined && value !== '' && trim(value) !== '') { + if (checkNull === false || (checkNull === true && value !== null)) { + return true; + } } - path = castPath(path, object); + return false; +}; - var index = -1, - length = path.length, - lastIndex = length - 1, - nested = object; +// Good practice rule - No magic number - while (nested != null && ++index < length) { - var key = toKey(path[index]), - newValue = value; +var 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)"; +var PARAMS_NOT_ARRAY_ERR = "params is not an array! Did something gone wrong when you generate the contract.json?"; +var EXCEPTION_CASE_ERR = 'Could not understand your arguments and parameter structure!'; - if (index != lastIndex) { - var objValue = nested[key]; - newValue = customizer ? customizer(objValue, key, nested) : undefined; - if (newValue === undefined) { - newValue = isObject(objValue) - ? objValue - : (isIndex(path[index + 1]) ? [] : {}); - } - } - assignValue(nested, key, newValue); - nested = nested[key]; - } - return object; -} +// primitive types /** - * The base implementation of `_.pickBy` without support for iteratee shorthands. - * - * @private - * @param {Object} object The source object. - * @param {string[]} paths The property paths to pick. - * @param {Function} predicate The function invoked per property. - * @returns {Object} Returns the new object. + * this is a wrapper method to call different one based on their type + * @param {string} type to check + * @return {function} a function to handle the type */ -function basePickBy(object, paths, predicate) { - var index = -1, - length = paths.length, - result = {}; - - while (++index < length) { - var path = paths[index], - value = baseGet(object, path); - - if (predicate(value, path)) { - baseSet(result, castPath(path, object), value); - } +var combineFn = function(type) { + switch (type) { + case NUMBER_TYPE: + return checkIsNumber + case STRING_TYPE: + return checkIsString + case BOOLEAN_TYPE: + return checkIsBoolean + default: + return checkIsAny } - return result; -} +}; -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeGetSymbols$1 = Object.getOwnPropertySymbols; +// validate array type /** - * Creates an array of the own and inherited enumerable symbols of `object`. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of symbols. + * @param {array} value expected + * @param {string} [type=''] pass the type if we encounter array. then we need to check the value as well + * @return {boolean} true if OK */ -var getSymbolsIn = !nativeGetSymbols$1 ? stubArray : function(object) { - var result = []; - while (object) { - arrayPush(result, getSymbols(object)); - object = getPrototype(object); +var checkIsArray = function(value, type) { + if ( type === void 0 ) type=''; + + if (isArray(value)) { + if (type === '' || trim(type)==='') { + return true; + } + // we test it in reverse + // @TODO if the type is an array (OR) then what? + // we need to take into account this could be an array + var c = value.filter(function (v) { return !combineFn(type)(v); }); + return !(c.length > 0) } - return result; + return false }; /** - * Creates an array of own and inherited enumerable property names and - * symbols of `object`. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names and symbols. + * check if it matches the array. pattern + * @param {string} type + * @return {boolean|array} false means NO, always return array */ -function getAllKeysIn(object) { - return baseGetAllKeys(object, keysIn, getSymbolsIn); -} +var isArrayLike$1 = function(type) { + // @TODO could that have something like array<> instead of array.<>? missing the dot? + // because type script is Array without the dot + if (type.indexOf(ARRAY_TYPE_LFT) > -1 && type.indexOf(ARRAY_TYPE_RGT) > -1) { + var _type = type.replace(ARRAY_TYPE_LFT, '').replace(ARRAY_TYPE_RGT, ''); + if (_type.indexOf(OR_SEPERATOR)) { + return _type.split(OR_SEPERATOR) + } + return [_type] + } + return false +}; /** - * Creates an object composed of the `object` properties `predicate` returns - * truthy for. The predicate is invoked with two arguments: (value, key). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Object - * @param {Object} object The source object. - * @param {Function} [predicate=_.identity] The function invoked per property. - * @returns {Object} Returns the new object. - * @example - * - * var object = { 'a': 1, 'b': '2', 'c': 3 }; - * - * _.pickBy(object, _.isNumber); - * // => { 'a': 1, 'c': 3 } + * we might encounter something like array. then we need to take it apart + * @param {object} p the prepared object for processing + * @param {string|array} type the type came from + * @return {boolean} for the filter to operate on */ -function pickBy(object, predicate) { - if (object == null) { - return {}; +var arrayTypeHandler = function(p, type) { + var arg = p.arg; + // need a special case to handle the OR type + // we need to test the args instead of the type(s) + if (type.length > 1) { + return !arg.filter(function (v) { return ( + !(type.length > type.filter(function (t) { return !combineFn(t)(v); }).length) + ); }).length } - var props = arrayMap(getAllKeysIn(object), function(prop) { - return [prop]; - }); - predicate = baseIteratee(predicate); - return basePickBy(object, props, function(value, path) { - return predicate(value, path[0]); - }); -} + // type is array so this will be or! + return type.length > type.filter(function (t) { return !checkIsArray(arg, t); }).length +}; +// validate object type /** - * The opposite of `_.pickBy`; this method creates an object composed of - * the own and inherited enumerable string keyed properties of `object` that - * `predicate` doesn't return truthy for. The predicate is invoked with two - * arguments: (value, key). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Object - * @param {Object} object The source object. - * @param {Function} [predicate=_.identity] The function invoked per property. - * @returns {Object} Returns the new object. - * @example - * - * var object = { 'a': 1, 'b': '2', 'c': 3 }; - * - * _.omitBy(object, _.isNumber); - * // => { 'b': '2' } + * @TODO if provide with the keys then we need to check if the key:value type as well + * @param {object} value expected + * @param {array} [keys=null] if it has the keys array to compare as well + * @return {boolean} true if OK */ -function omitBy(object, predicate) { - return pickBy(object, negate(baseIteratee(predicate))); -} +var checkIsObject = function(value, keys) { + if ( keys === void 0 ) keys=null; + + if (isPlainObject(value)) { + if (!keys) { + return true + } + if (checkIsArray(keys)) { + // please note we DON'T care if some is optional + // plese refer to the contract.json for the keys + return !keys.filter(function (key) { + var _value = value[key.name]; + return !(key.type.length > key.type.filter(function (type) { + var tmp; + if (_value !== undefined) { + if ((tmp = isArrayLike$1(type)) !== false) { + return !arrayTypeHandler({arg: _value}, tmp) + // return tmp.filter(t => !checkIsArray(_value, t)).length; + // @TODO there might be an object within an object with keys as well :S + } + return !combineFn(type)(_value) + } + return true + }).length) + }).length; + } + } + return false +}; /** - * Performs a deep comparison between two values to determine if they are - * equivalent. - * - * **Note:** This method supports comparing arrays, array buffers, booleans, - * date objects, error objects, maps, numbers, `Object` objects, regexes, - * sets, strings, symbols, and typed arrays. `Object` objects are compared - * by their own, not inherited, enumerable properties. Functions and DOM - * nodes are compared by strict equality, i.e. `===`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - * @example - * - * var object = { 'a': 1 }; - * var other = { 'a': 1 }; - * - * _.isEqual(object, other); - * // => true - * - * object === other; - * // => false - */ -function isEqual(value, other) { - return baseIsEqual(value, other); -} - -/** - * The base implementation of methods like `_.findKey` and `_.findLastKey`, - * without support for iteratee shorthands, which iterates over `collection` - * using `eachFunc`. - * - * @private - * @param {Array|Object} collection The collection to inspect. - * @param {Function} predicate The function invoked per iteration. - * @param {Function} eachFunc The function to iterate over `collection`. - * @returns {*} Returns the found element or its key, else `undefined`. - */ -function baseFindKey(collection, predicate, eachFunc) { - var result; - eachFunc(collection, function(value, key, collection) { - if (predicate(value, key, collection)) { - result = key; - return false; - } - }); - return result; -} - -/** - * This method is like `_.find` except that it returns the key of the first - * element `predicate` returns truthy for instead of the element itself. - * - * @static - * @memberOf _ - * @since 1.1.0 - * @category Object - * @param {Object} object The object to inspect. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @returns {string|undefined} Returns the key of the matched element, - * else `undefined`. - * @example - * - * var users = { - * 'barney': { 'age': 36, 'active': true }, - * 'fred': { 'age': 40, 'active': false }, - * 'pebbles': { 'age': 1, 'active': true } - * }; - * - * _.findKey(users, function(o) { return o.age < 40; }); - * // => 'barney' (iteration order is not guaranteed) - * - * // The `_.matches` iteratee shorthand. - * _.findKey(users, { 'age': 1, 'active': true }); - * // => 'pebbles' - * - * // The `_.matchesProperty` iteratee shorthand. - * _.findKey(users, ['active', false]); - * // => 'fred' - * - * // The `_.property` iteratee shorthand. - * _.findKey(users, 'active'); - * // => 'barney' - */ -function findKey(object, predicate) { - return baseFindKey(object, baseIteratee(predicate), baseForOwn); -} - -/** - * @param {array} arr Array for check - * @param {*} value target - * @return {boolean} true on successs + * fold this into it's own function to handler different object type + * @param {object} p the prepared object for process + * @return {boolean} */ -var isInArray = function(arr, value) { - return !!arr.filter(function (a) { return a === value; }).length -}; - -var isObjectHasKey = function(obj, key) { - var keys = Object.keys(obj); - return isInArray(keys, key) +var objectTypeHandler = function(p) { + var arg = p.arg; + var param = p.param; + var _args = [arg]; + if (Array.isArray(param.keys) && param.keys.length) { + _args.push(param.keys); + } + // just simple check + return Reflect.apply(checkIsObject, null, _args) }; -// just not to make my head hurt -var isEmpty = function (value) { return !isNotEmpty(value); }; +// move the index.js code here that make more sense to find where things are +// import debug from 'debug' +// const debugFn = debug('jsonql-params-validator:validator') +// also export this for use in other places /** - * Map the alias to their key then grab their value over - * @param {object} config the user supplied config - * @param {object} appProps the default option map - * @return {object} the config keys replaced with the appProps key by the ALIAS + * We need to handle those optional parameter without a default value + * @param {object} params from contract.json + * @return {boolean} for filter operation false is actually OK */ -function mapAliasConfigKeys(config, appProps) { - // need to do two steps - // 1. take key with alias key - var aliasMap = omitBy(appProps, function (value, k) { return !value[ALIAS_KEY]; } ); - if (isEqual(aliasMap, {})) { - return config; +var optionalHandler = function( params ) { + var arg = params.arg; + var param = params.param; + if (isNotEmpty(arg)) { + // debug('call optional handler', arg, params); + // loop through the type in param + return !(param.type.length > param.type.filter(function (type) { return validateHandler(type, params); } + ).length) } - return mapKeys(config, function (v, key) { return findKey(aliasMap, function (o) { return o.alias === key; }) || key; }) -} + return false +}; /** - * We only want to run the valdiation against the config (user supplied) value - * but keep the defaultOptions untouch - * @param {object} config configuraton supplied by user - * @param {object} appProps the default options map - * @return {object} the pristine values that will add back to the final output + * actually picking the validator + * @param {*} type for checking + * @param {*} value for checking + * @return {boolean} true on OK */ -function preservePristineValues(config, appProps) { - // @BUG this will filter out those that is alias key - // we need to first map the alias keys back to their full key - var _config = mapAliasConfigKeys(config, appProps); - // take the default value out - var pristineValues = mapValues( - omitBy(appProps, function (value, key) { return isObjectHasKey(_config, key); }), - function (value) { return value.args; } - ); - // for testing the value - var checkAgainstAppProps = omitBy(appProps, function (value, key) { return !isObjectHasKey(_config, key); }); - // output - return { - pristineValues: pristineValues, - checkAgainstAppProps: checkAgainstAppProps, - config: _config // passing this correct values back +var validateHandler = function(type, value) { + var tmp; + switch (true) { + case type === OBJECT_TYPE: + // debugFn('call OBJECT_TYPE') + return !objectTypeHandler(value) + case type === ARRAY_TYPE: + // debugFn('call ARRAY_TYPE') + return !checkIsArray(value.arg) + // @TODO when the type is not present, it always fall through here + // so we need to find a way to actually pre-check the type first + // AKA check the contract.json map before running here + case (tmp = isArrayLike$1(type)) !== false: + // debugFn('call ARRAY_LIKE: %O', value) + return !arrayTypeHandler(value, tmp) + default: + return !combineFn(type)(value.arg) } -} +}; /** - * This will take the value that is ONLY need to check - * @param {object} config that one - * @param {object} props map for creating checking - * @return {object} put that arg into the args + * it get too longer to fit in one line so break it out from the fn below + * @param {*} arg value + * @param {object} param config + * @return {*} value or apply default value */ -function processConfigAction(config, props) { - // debugFn('processConfigAction', props) - // v.1.2.0 add checking if its mark optional and the value is empty then pass - return mapValues(props, function (value, key) { - var obj, obj$1; - - return ( - config[key] === undefined || (value[OPTIONAL_KEY] === true && isEmpty(config[key])) - ? merge({}, value, ( obj = {}, obj[KEY_WORD] = true, obj )) - : ( obj$1 = {}, obj$1[ARGS_KEY] = config[key], obj$1[TYPE_KEY] = value[TYPE_KEY], obj$1[OPTIONAL_KEY] = value[OPTIONAL_KEY] || false, obj$1[ENUM_KEY] = value[ENUM_KEY] || false, obj$1[CHECKER_KEY] = value[CHECKER_KEY] || false, obj$1 ) - ); +var getOptionalValue = function(arg, param) { + if (arg !== undefined) { + return arg } - ) -} + return (param.optional === true && param.defaultvalue !== undefined ? param.defaultvalue : null) +}; /** - * Quick transform - * @TODO we should only validate those that is pass from the config - * and pass through those values that is from the defaultOptions - * @param {object} opts that one - * @param {object} appProps mutation configuration options - * @return {object} put that arg into the args + * padding the arguments with defaultValue if the arguments did not provide the value + * this will be the name export + * @param {array} args normalized arguments + * @param {array} params from contract.json + * @return {array} merge the two together */ -function prepareArgsForValidation(opts, appProps) { - var ref = preservePristineValues(opts, appProps); - var config = ref.config; - var pristineValues = ref.pristineValues; - var checkAgainstAppProps = ref.checkAgainstAppProps; - // output - return [ - processConfigAction(config, checkAgainstAppProps), - pristineValues - ] -} - -// this get throw from within the checkOptions when run through the enum failed -var JsonqlEnumError = /*@__PURE__*/(function (Error) { - function JsonqlEnumError() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - Error.apply(this, args); - - this.message = args[0]; - this.detail = args[1]; - - this.className = JsonqlEnumError.name; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlEnumError); - } +var normalizeArgs = function(args, params) { + // first we should check if this call require a validation at all + // there will be situation where the function doesn't need args and params + if (!checkIsArray(params)) { + // debugFn('params value', params) + throw new JsonqlValidationError(PARAMS_NOT_ARRAY_ERR) } - - if ( Error ) JsonqlEnumError.__proto__ = Error; - JsonqlEnumError.prototype = Object.create( Error && Error.prototype ); - JsonqlEnumError.prototype.constructor = JsonqlEnumError; - - var staticAccessors = { name: { configurable: true } }; - - staticAccessors.name.get = function () { - return 'JsonqlEnumError' - }; - - Object.defineProperties( JsonqlEnumError, staticAccessors ); - - return JsonqlEnumError; -}(Error)); - -// this will throw from inside the checkOptions -var JsonqlTypeError = /*@__PURE__*/(function (Error) { - function JsonqlTypeError() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - Error.apply(this, args); - - this.message = args[0]; - this.detail = args[1]; - - this.className = JsonqlTypeError.name; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlTypeError); - } + if (params.length === 0) { + return [] } - - if ( Error ) JsonqlTypeError.__proto__ = Error; - JsonqlTypeError.prototype = Object.create( Error && Error.prototype ); - JsonqlTypeError.prototype.constructor = JsonqlTypeError; - - var staticAccessors = { name: { configurable: true } }; - - staticAccessors.name.get = function () { - return 'JsonqlTypeError' - }; - - Object.defineProperties( JsonqlTypeError, staticAccessors ); - - return JsonqlTypeError; -}(Error)); - -// allow supply a custom checker function -// if that failed then we throw this error -var JsonqlCheckerError = /*@__PURE__*/(function (Error) { - function JsonqlCheckerError() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - Error.apply(this, args); - this.message = args[0]; - this.detail = args[1]; - - this.className = JsonqlCheckerError.name; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlCheckerError); - } + if (!checkIsArray(args)) { + throw new JsonqlValidationError(ARGS_NOT_ARRAY_ERR) } + // debugFn(args, params); + // fall through switch + switch(true) { + case args.length == params.length: // standard + return args.map(function (arg, i) { return ( + { + arg: arg, + index: i, + param: params[i] + } + ); }) + case params[0].variable === true: // using spread syntax + var type = params[0].type; + return args.map(function (arg, i) { return ( + { + arg: arg, + index: i, // keep the index for reference + param: params[i] || { type: type, name: '_' } + } + ); }) + // with optional defaultValue parameters + case args.length < params.length: + return params.map(function (param, i) { return ( + { + param: param, + index: i, + arg: getOptionalValue(args[i], param), + optional: param.optional || false + } + ); }) + // this one pass more than it should have anything after the args.length will be cast as any type + case args.length > params.length: + var ctn = params.length; + // this happens when we have those array. type + var _type = [ DEFAULT_TYPE ]; + // we only looking at the first one, this might be a @BUG + /* + if ((tmp = isArrayLike(params[0].type[0])) !== false) { + _type = tmp; + } */ + // if we use the params as guide then the rest will get throw out + // which is not what we want, instead, anything without the param + // will get a any type and optional flag + return args.map(function (arg, i) { + var optional = i >= ctn ? true : !!params[i].optional; + var param = params[i] || { type: _type, name: ("_" + i) }; + return { + arg: optional ? getOptionalValue(arg, param) : arg, + index: i, + param: param, + optional: optional + } + }) + // @TODO find out if there is more cases not cover + default: // this should never happen + // debugFn('args', args) + // debugFn('params', params) + // this is unknown therefore we just throw it! + throw new JsonqlError$1(EXCEPTION_CASE_ERR, { args: args, params: params }) + } +}; - if ( Error ) JsonqlCheckerError.__proto__ = Error; - JsonqlCheckerError.prototype = Object.create( Error && Error.prototype ); - JsonqlCheckerError.prototype.constructor = JsonqlCheckerError; - - var staticAccessors = { name: { configurable: true } }; - - staticAccessors.name.get = function () { - return 'JsonqlCheckerError' - }; - - Object.defineProperties( JsonqlCheckerError, staticAccessors ); - - return JsonqlCheckerError; -}(Error)); - -// breaking the whole thing up to see what cause the multiple calls issue - -// import debug from 'debug'; -// const debugFn = debug('jsonql-params-validator:options:validation') - -/** - * just make sure it returns an array to use - * @param {*} arg input - * @return {array} output - */ -var toArray = function (arg) { return checkIsArray(arg) ? arg : [arg]; }; - +// what we want is after the validaton we also get the normalized result +// which is with the optional property if the argument didn't provide it /** - * DIY in array - * @param {array} arr to check against - * @param {*} value to check - * @return {boolean} true on OK + * process the array of params back to their arguments + * @param {array} result the params result + * @return {array} arguments */ -var inArray = function (arr, value) { return ( - !!arr.filter(function (v) { return v === value; }).length -); }; +var processReturn = function (result) { return result.map(function (r) { return r.arg; }); }; /** - * break out to make the code easier to read - * @param {object} value to process - * @param {function} cb the validateSync - * @return {array} empty on success + * validator main interface + * @param {array} args the arguments pass to the method call + * @param {array} params from the contract for that method + * @param {boolean} [withResul=false] if true then this will return the normalize result as well + * @return {array} empty array on success, or failed parameter and reasons */ -function validateHandler$1(value, cb) { +var validateSync = function(args, params, withResult) { var obj; - // cb is the validateSync methods - var args = [ - [ value[ARGS_KEY] ], - [( obj = {}, obj[TYPE_KEY] = toArray(value[TYPE_KEY]), obj[OPTIONAL_KEY] = value[OPTIONAL_KEY], obj )] - ]; - // debugFn('validateHandler', args) - return Reflect.apply(cb, null, args) -} - -/** - * Check against the enum value if it's provided - * @param {*} value to check - * @param {*} enumv to check against if it's not false - * @return {boolean} true on OK - */ -var enumHandler = function (value, enumv) { - if (checkIsArray(enumv)) { - return inArray(enumv, value) - } - return true + if ( withResult === void 0 ) withResult = false; + var cleanArgs = normalizeArgs(args, params); + var checkResult = cleanArgs.filter(function (p) { + // v1.4.4 this fixed the problem, the root level optional is from the last fn + if (p.optional === true || p.param.optional === true) { + return optionalHandler(p) + } + // because array of types means OR so if one pass means pass + return !(p.param.type.length > p.param.type.filter( + function (type) { return validateHandler(type, p); } + ).length) + }); + // using the same convention we been using all this time + return !withResult ? checkResult : ( obj = {}, obj[ERROR_KEY] = checkResult, obj[DATA_KEY] = processReturn(cleanArgs), obj ) }; /** - * Allow passing a function to check the value - * There might be a problem here if the function is incorrect - * and that will makes it hard to debug what is going on inside - * @TODO there could be a few feature add to this one under different circumstance - * @param {*} value to check - * @param {function} checker for checking + * A wrapper method that return promise + * @param {array} args arguments + * @param {array} params from contract.json + * @param {boolean} [withResul=false] if true then this will return the normalize result as well + * @return {object} promise.then or catch */ -var checkerHandler = function (value, checker) { - try { - return isFunction(checker) ? checker.apply(null, [value]) : false - } catch (e) { - return false - } +var validateAsync = function(args, params, withResult) { + if ( withResult === void 0 ) withResult = false; + + return new Promise(function (resolver, rejecter) { + var result = validateSync(args, params, withResult); + if (withResult) { + return result[ERROR_KEY].length ? rejecter(result[ERROR_KEY]) + : resolver(result[DATA_KEY]) + } + // the different is just in the then or catch phrase + return result.length ? rejecter(result) : resolver([]) + }) }; +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeKeys = overArg(Object.keys, Object); + +/** Used for built-in method references. */ +var objectProto$b = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$9 = objectProto$b.hasOwnProperty; + /** - * Taken out from the runValidaton this only validate the required values - * @param {array} args from the config2argsAction - * @param {function} cb validateSync - * @return {array} of configuration values + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. */ -function runValidationAction(cb) { - return function (value, key) { - // debugFn('runValidationAction', key, value) - if (value[KEY_WORD]) { - return value[ARGS_KEY] - } - var check = validateHandler$1(value, cb); - if (check.length) { - // log('runValidationAction', key, value) - throw new JsonqlTypeError(key, check) - } - if (value[ENUM_KEY] !== false && !enumHandler(value[ARGS_KEY], value[ENUM_KEY])) { - // log(ENUM_KEY, value[ENUM_KEY]) - throw new JsonqlEnumError(key) - } - if (value[CHECKER_KEY] !== false && !checkerHandler(value[ARGS_KEY], value[CHECKER_KEY])) { - // log(CHECKER_KEY, value[CHECKER_KEY]) - throw new JsonqlCheckerError(key) +function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty$9.call(object, key) && key != 'constructor') { + result.push(key); } - return value[ARGS_KEY] } + return result; } /** - * @param {object} args from the config2argsAction - * @param {function} cb validateSync - * @return {object} of configuration values + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] */ -function runValidation(args, cb) { - var argsForValidate = args[0]; - var pristineValues = args[1]; - // turn the thing into an array and see what happen here - // debugFn('_args', argsForValidate) - var result = mapValues(argsForValidate, runValidationAction(cb)); - return merge(result, pristineValues) +function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); } -/// this is port back from the client to share across all projects +/** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ +function baseForOwn(object, iteratee) { + return object && baseFor(object, iteratee, keys); +} -// import debug from 'debug' -// const debugFn = debug('jsonql-params-validator:check-options-async') +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED$2 = '__lodash_hash_undefined__'; /** - * Quick transform - * @param {object} config that one - * @param {object} appProps mutation configuration options - * @return {object} put that arg into the args + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. */ -var configToArgs = function (config, appProps) { - return Promise.resolve( - prepareArgsForValidation(config, appProps) - ) -}; +function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED$2); + return this; +} /** - * @param {object} config user provide configuration option - * @param {object} appProps mutation configuration options - * @param {object} constProps the immutable configuration options - * @param {function} cb the validateSync method - * @return {object} Promise resolve merge config object + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. */ -function checkOptionsAsync(config, appProps, constProps, cb) { - if ( config === void 0 ) config = {}; - - return configToArgs(config, appProps) - .then(function (args1) { return runValidation(args1, cb); }) - // next if every thing good then pass to final merging - .then(function (args2) { return merge({}, args2, constProps); }) +function setCacheHas(value) { + return this.__data__.has(value); } -// create function to construct the config entry so we don't need to keep building object -// import checkIsBoolean from '../boolean' -// import debug from 'debug'; -// const debugFn = debug('jsonql-params-validator:construct-config'); /** - * @param {*} args value - * @param {string} type for value - * @param {boolean} [optional=false] - * @param {boolean|array} [enumv=false] - * @param {boolean|function} [checker=false] - * @return {object} config entry + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. */ -function constructConfig(args, type, optional, enumv, checker, alias) { - if ( optional === void 0 ) optional=false; - if ( enumv === void 0 ) enumv=false; - if ( checker === void 0 ) checker=false; - if ( alias === void 0 ) alias=false; +function SetCache(values) { + var index = -1, + length = values == null ? 0 : values.length; - var base = {}; - base[ARGS_KEY] = args; - base[TYPE_KEY] = type; - if (optional === true) { - base[OPTIONAL_KEY] = true; - } - if (checkIsArray(enumv)) { - base[ENUM_KEY] = enumv; - } - if (isFunction(checker)) { - base[CHECKER_KEY] = checker; - } - if (isString(alias)) { - base[ALIAS_KEY] = alias; + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); } - return base } -// export also create wrapper methods +// Add methods to `SetCache`. +SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; +SetCache.prototype.has = setCacheHas; /** - * This has a different interface - * @param {*} value to supply - * @param {string|array} type for checking - * @param {object} params to map against the config check - * @param {array} params.enumv NOT enum - * @param {boolean} params.optional false then nothing - * @param {function} params.checker need more work on this one later - * @param {string} params.alias mostly for cmd + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. */ -var createConfig = function (value, type, params) { - if ( params === void 0 ) params = {}; +function arraySome(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; - // Note the enumv not ENUM - // const { enumv, optional, checker, alias } = params; - // let args = [value, type, optional, enumv, checker, alias]; - var o = params[OPTIONAL_KEY]; - var e = params[ENUM_KEY]; - var c = params[CHECKER_KEY]; - var a = params[ALIAS_KEY]; - return constructConfig.apply(null, [value, type, o, e, c, a]) -}; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; +} /** - * construct the actual end user method, rename with prefix get since 1.5.2 - * @param {function} validateSync validation method - * @return {function} for performaning the actual valdiation + * Checks if a `cache` value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ -var getCheckConfigAsync = function(validateSync) { - /** - * We recreate the method here to avoid the circlar import - * @param {object} config user supply configuration - * @param {object} appProps mutation options - * @param {object} [constantProps={}] optional: immutation options - * @return {object} all checked configuration - */ - return function(config, appProps, constantProps) { - if ( constantProps === void 0 ) constantProps= {}; +function cacheHas(cache, key) { + return cache.has(key); +} - return checkOptionsAsync(config, appProps, constantProps, validateSync) - } -}; +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; /** - * This is a custom error to throw when server throw a 406 - * This help us to capture the right error, due to the call happens in sequence - * @param {string} message to tell what happen - * @param {mixed} extra things we want to add, 500? + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. */ -var Jsonql406Error = /*@__PURE__*/(function (Error) { - function Jsonql406Error() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - Error.apply(this, args); - this.message = args[0]; - this.detail = args[1]; - // We can't access the static name from an instance - // but we can do it like this - this.className = Jsonql406Error.name; +function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, Jsonql406Error); - } + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; } + // Assume cyclic values are equal. + var stacked = stack.get(array); + if (stacked && stack.get(other)) { + return stacked == other; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; - if ( Error ) Jsonql406Error.__proto__ = Error; - Jsonql406Error.prototype = Object.create( Error && Error.prototype ); - Jsonql406Error.prototype.constructor = Jsonql406Error; - - var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; - - staticAccessors.statusCode.get = function () { - return NOT_ACCEPTABLE_STATUS - }; - - staticAccessors.name.get = function () { - return 'Jsonql406Error' - }; + stack.set(array, other); + stack.set(other, array); - Object.defineProperties( Jsonql406Error, staticAccessors ); + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; - return Jsonql406Error; -}(Error)); + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; +} /** - * This is a custom error to throw when server throw a 500 - * This help us to capture the right error, due to the call happens in sequence - * @param {string} message to tell what happen - * @param {mixed} extra things we want to add, 500? + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. */ -var Jsonql500Error = /*@__PURE__*/(function (Error) { - function Jsonql500Error() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - Error.apply(this, args); - - this.message = args[0]; - this.detail = args[1]; - - this.className = Jsonql500Error.name; +function mapToArray(map) { + var index = -1, + result = Array(map.size); - if (Error.captureStackTrace) { - Error.captureStackTrace(this, Jsonql500Error); - } - } + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; +} - if ( Error ) Jsonql500Error.__proto__ = Error; - Jsonql500Error.prototype = Object.create( Error && Error.prototype ); - Jsonql500Error.prototype.constructor = Jsonql500Error; +/** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ +function setToArray(set) { + var index = -1, + result = Array(set.size); - var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; + set.forEach(function(value) { + result[++index] = value; + }); + return result; +} - staticAccessors.statusCode.get = function () { - return SERVER_INTERNAL_STATUS - }; +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG$1 = 1, + COMPARE_UNORDERED_FLAG$1 = 2; - staticAccessors.name.get = function () { - return 'Jsonql500Error' - }; +/** `Object#toString` result references. */ +var boolTag$1 = '[object Boolean]', + dateTag$1 = '[object Date]', + errorTag$1 = '[object Error]', + mapTag$1 = '[object Map]', + numberTag$2 = '[object Number]', + regexpTag$1 = '[object RegExp]', + setTag$1 = '[object Set]', + stringTag$2 = '[object String]', + symbolTag$1 = '[object Symbol]'; - Object.defineProperties( Jsonql500Error, staticAccessors ); +var arrayBufferTag$1 = '[object ArrayBuffer]', + dataViewTag$1 = '[object DataView]'; - return Jsonql500Error; -}(Error)); +/** Used to convert symbols to primitives and strings. */ +var symbolProto$1 = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto$1 ? symbolProto$1.valueOf : undefined; /** - * this is the 403 Forbidden error - * that means this user is not login - * use the 401 for try to login and failed - * @param {string} message to tell what happen - * @param {mixed} extra things we want to add, 500? + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ -var JsonqlForbiddenError = /*@__PURE__*/(function (Error) { - function JsonqlForbiddenError() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; +function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag$1: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; - Error.apply(this, args); - this.message = args[0]; - this.detail = args[1]; + case arrayBufferTag$1: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; - this.className = JsonqlForbiddenError.name; + case boolTag$1: + case dateTag$1: + case numberTag$2: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlForbiddenError); - } - } + case errorTag$1: + return object.name == other.name && object.message == other.message; - if ( Error ) JsonqlForbiddenError.__proto__ = Error; - JsonqlForbiddenError.prototype = Object.create( Error && Error.prototype ); - JsonqlForbiddenError.prototype.constructor = JsonqlForbiddenError; + case regexpTag$1: + case stringTag$2: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); - var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; + case mapTag$1: + var convert = mapToArray; - staticAccessors.statusCode.get = function () { - return FORBIDDEN_STATUS - }; + case setTag$1: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG$1; + convert || (convert = setToArray); - staticAccessors.name.get = function () { - return 'JsonqlForbiddenError'; - }; + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG$1; - Object.defineProperties( JsonqlForbiddenError, staticAccessors ); + // Recursively compare objects (susceptible to call stack limits). + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack['delete'](object); + return result; - return JsonqlForbiddenError; -}(Error)); + case symbolTag$1: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; +} /** - * This is a custom error to throw when pass credential but fail - * This help us to capture the right error, due to the call happens in sequence - * @param {string} message to tell what happen - * @param {mixed} extra things we want to add, 500? + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. */ -var JsonqlAuthorisationError = /*@__PURE__*/(function (Error) { - function JsonqlAuthorisationError() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - Error.apply(this, args); - this.message = args[0]; - this.detail = args[1]; - - this.className = JsonqlAuthorisationError.name; +function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlAuthorisationError); - } + while (++index < length) { + array[offset + index] = values[index]; } - - if ( Error ) JsonqlAuthorisationError.__proto__ = Error; - JsonqlAuthorisationError.prototype = Object.create( Error && Error.prototype ); - JsonqlAuthorisationError.prototype.constructor = JsonqlAuthorisationError; - - var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; - - staticAccessors.statusCode.get = function () { - return UNAUTHORIZED_STATUS - }; - - staticAccessors.name.get = function () { - return 'JsonqlAuthorisationError'; - }; - - Object.defineProperties( JsonqlAuthorisationError, staticAccessors ); - - return JsonqlAuthorisationError; -}(Error)); + return array; +} /** - * This is a custom error when not supply the credential and try to get contract - * This help us to capture the right error, due to the call happens in sequence - * @param {string} message to tell what happen - * @param {mixed} extra things we want to add, 500? + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. */ -var JsonqlContractAuthError = /*@__PURE__*/(function (Error) { - function JsonqlContractAuthError() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - Error.apply(this, args); - this.message = args[0]; - this.detail = args[1]; +function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); +} - this.className = JsonqlContractAuthError.name; +/** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ +function arrayFilter(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlContractAuthError); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; } } - - if ( Error ) JsonqlContractAuthError.__proto__ = Error; - JsonqlContractAuthError.prototype = Object.create( Error && Error.prototype ); - JsonqlContractAuthError.prototype.constructor = JsonqlContractAuthError; - - var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; - - staticAccessors.statusCode.get = function () { - return UNAUTHORIZED_STATUS - }; - - staticAccessors.name.get = function () { - return 'JsonqlContractAuthError' - }; - - Object.defineProperties( JsonqlContractAuthError, staticAccessors ); - - return JsonqlContractAuthError; -}(Error)); + return result; +} /** - * This is a custom error to throw when the resolver throw error and capture inside the middleware - * This help us to capture the right error, due to the call happens in sequence - * @param {string} message to tell what happen - * @param {mixed} extra things we want to add, 500? + * This method returns a new empty array. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {Array} Returns the new empty array. + * @example + * + * var arrays = _.times(2, _.stubArray); + * + * console.log(arrays); + * // => [[], []] + * + * console.log(arrays[0] === arrays[1]); + * // => false */ -var JsonqlResolverAppError = /*@__PURE__*/(function (Error) { - function JsonqlResolverAppError() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; +function stubArray() { + return []; +} - Error.apply(this, args); +/** Used for built-in method references. */ +var objectProto$c = Object.prototype; - this.message = args[0]; - this.detail = args[1]; +/** Built-in value references. */ +var propertyIsEnumerable$1 = objectProto$c.propertyIsEnumerable; - this.className = JsonqlResolverAppError.name; +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetSymbols = Object.getOwnPropertySymbols; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlResolverAppError); - } +/** + * Creates an array of the own enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ +var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; } + object = Object(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable$1.call(object, symbol); + }); +}; - if ( Error ) JsonqlResolverAppError.__proto__ = Error; - JsonqlResolverAppError.prototype = Object.create( Error && Error.prototype ); - JsonqlResolverAppError.prototype.constructor = JsonqlResolverAppError; - - var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; - - staticAccessors.statusCode.get = function () { - return SERVER_INTERNAL_STATUS - }; +/** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ +function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); +} - staticAccessors.name.get = function () { - return 'JsonqlResolverAppError' - }; +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG$2 = 1; - Object.defineProperties( JsonqlResolverAppError, staticAccessors ); +/** Used for built-in method references. */ +var objectProto$d = Object.prototype; - return JsonqlResolverAppError; -}(Error)); +/** Used to check objects for own properties. */ +var hasOwnProperty$a = objectProto$d.hasOwnProperty; /** - * This is a custom error to throw when could not find the resolver - * This help us to capture the right error, due to the call happens in sequence - * @param {string} message to tell what happen - * @param {mixed} extra things we want to add, 500? + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ -var JsonqlResolverNotFoundError = /*@__PURE__*/(function (Error) { - function JsonqlResolverNotFoundError() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - Error.apply(this, args); - - this.message = args[0]; - this.detail = args[1]; - - this.className = JsonqlResolverNotFoundError.name; +function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG$2, + objProps = getAllKeys(object), + objLength = objProps.length, + othProps = getAllKeys(other), + othLength = othProps.length; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlResolverNotFoundError); + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty$a.call(other, key))) { + return false; } } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked && stack.get(other)) { + return stacked == other; + } + var result = true; + stack.set(object, other); + stack.set(other, object); - if ( Error ) JsonqlResolverNotFoundError.__proto__ = Error; - JsonqlResolverNotFoundError.prototype = Object.create( Error && Error.prototype ); - JsonqlResolverNotFoundError.prototype.constructor = JsonqlResolverNotFoundError; - - var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; - - staticAccessors.statusCode.get = function () { - return NOT_FOUND_STATUS - }; - - staticAccessors.name.get = function () { - return 'JsonqlResolverNotFoundError'; - }; - - Object.defineProperties( JsonqlResolverNotFoundError, staticAccessors ); - - return JsonqlResolverNotFoundError; -}(Error)); + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; -// this is from an example from Koa team to use for internal middleware ctx.throw -// but after the test the res.body part is unable to extract the required data -// I keep this one here for future reference + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; -var JsonqlServerError = /*@__PURE__*/(function (Error) { - function JsonqlServerError(statusCode, message) { - Error.call(this, message); - this.statusCode = statusCode; - this.className = JsonqlServerError.name; + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } } + stack['delete'](object); + stack['delete'](other); + return result; +} - if ( Error ) JsonqlServerError.__proto__ = Error; - JsonqlServerError.prototype = Object.create( Error && Error.prototype ); - JsonqlServerError.prototype.constructor = JsonqlServerError; +/* Built-in method references that are verified to be native. */ +var DataView = getNative(root, 'DataView'); - var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; +/* Built-in method references that are verified to be native. */ +var Promise$1 = getNative(root, 'Promise'); - staticAccessors.statusCode.get = function () { - return SERVER_INTERNAL_STATUS - }; +/* Built-in method references that are verified to be native. */ +var Set$1 = getNative(root, 'Set'); - staticAccessors.name.get = function () { - return 'JsonqlServerError' - }; +/* Built-in method references that are verified to be native. */ +var WeakMap$1 = getNative(root, 'WeakMap'); - Object.defineProperties( JsonqlServerError, staticAccessors ); +/** `Object#toString` result references. */ +var mapTag$2 = '[object Map]', + objectTag$2 = '[object Object]', + promiseTag = '[object Promise]', + setTag$2 = '[object Set]', + weakMapTag$1 = '[object WeakMap]'; - return JsonqlServerError; -}(Error)); +var dataViewTag$2 = '[object DataView]'; + +/** Used to detect maps, sets, and weakmaps. */ +var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map$1), + promiseCtorString = toSource(Promise$1), + setCtorString = toSource(Set$1), + weakMapCtorString = toSource(WeakMap$1); /** - * this will put into generator call at the very end and catch - * the error throw from inside then throw again - * this is necessary because we split calls inside and the throw - * will not reach the actual client unless we do it this way - * @param {object} e Error - * @return {void} just throw + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. */ -function finalCatch(e) { - // this is a hack to get around the validateAsync not actually throw error - // instead it just rejected it with the array of failed parameters - if (Array.isArray(e)) { - // if we want the message then I will have to create yet another function - // to wrap this function to provide the name prop - throw new JsonqlValidationError('', e) - } - var msg = e.message || NO_ERROR_MSG; - var detail = e.detail || e; - // @BUG the instance of not always work for some reason! - // need to figure out a better way to find out the type of the error - switch (true) { - case e instanceof Jsonql406Error: - throw new Jsonql406Error(msg, detail) - case e instanceof Jsonql500Error: - throw new Jsonql500Error(msg, detail) - case e instanceof JsonqlForbiddenError: - throw new JsonqlForbiddenError(msg, detail) - case e instanceof JsonqlAuthorisationError: - throw new JsonqlAuthorisationError(msg, detail) - case e instanceof JsonqlContractAuthError: - throw new JsonqlContractAuthError(msg, detail) - case e instanceof JsonqlResolverAppError: - throw new JsonqlResolverAppError(msg, detail) - case e instanceof JsonqlResolverNotFoundError: - throw new JsonqlResolverNotFoundError(msg, detail) - case e instanceof JsonqlEnumError: - throw new JsonqlEnumError(msg, detail) - case e instanceof JsonqlTypeError: - throw new JsonqlTypeError(msg, detail) - case e instanceof JsonqlCheckerError: - throw new JsonqlCheckerError(msg, detail) - case e instanceof JsonqlValidationError: - throw new JsonqlValidationError(msg, detail) - case e instanceof JsonqlServerError: - throw new JsonqlServerError(msg, detail) - default: - throw new JsonqlError$1(msg, detail) - } +var getTag = baseGetTag; + +// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. +if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag$2) || + (Map$1 && getTag(new Map$1) != mapTag$2) || + (Promise$1 && getTag(Promise$1.resolve()) != promiseTag) || + (Set$1 && getTag(new Set$1) != setTag$2) || + (WeakMap$1 && getTag(new WeakMap$1) != weakMapTag$1)) { + getTag = function(value) { + var result = baseGetTag(value), + Ctor = result == objectTag$2 ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : ''; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag$2; + case mapCtorString: return mapTag$2; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag$2; + case weakMapCtorString: return weakMapTag$1; + } + } + return result; + }; } -// export -var isString$1 = checkIsString; -var validateAsync$1 = validateAsync; +var getTag$1 = getTag; -var createConfig$1 = createConfig; -// construct the final output 1.5.2 -var checkConfigAsync = getCheckConfigAsync(validateSync); +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG$3 = 1; -// move the get logger stuff here +/** `Object#toString` result references. */ +var argsTag$2 = '[object Arguments]', + arrayTag$1 = '[object Array]', + objectTag$3 = '[object Object]'; -// it does nothing -var dummyLogger = function () {}; +/** Used for built-in method references. */ +var objectProto$e = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$b = objectProto$e.hasOwnProperty; /** - * re-use the debugOn prop to control this log method - * @param {object} opts configuration - * @return {function} the log function + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ -var getLogger = function (opts) { - var debugOn = opts.debugOn; - if (debugOn) { - return function () { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; +function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = objIsArr ? arrayTag$1 : getTag$1(object), + othTag = othIsArr ? arrayTag$1 : getTag$1(other); - Reflect.apply(console.info, console, ['[jsonql-ws-client-core]' ].concat( args)); + objTag = objTag == argsTag$2 ? objectTag$3 : objTag; + othTag = othTag == argsTag$2 ? objectTag$3 : othTag; + + var objIsObj = objTag == objectTag$3, + othIsObj = othTag == objectTag$3, + isSameTag = objTag == othTag; + + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; } + objIsArr = true; + objIsObj = false; } - return dummyLogger -}; - -/** - * Make sure there is a log method - * @param {object} opts configuration - * @return {object} opts - */ -var getLogFn = function (opts) { - var log = opts.log; // 1.3.9 if we pass a log method here then we use this - if (!log || typeof log !== 'function') { - return getLogger(opts) + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); } - opts.log('---> getLogFn user supplied log function <---', opts); - return log -}; - -// group all the repetitive message here + if (!(bitmask & COMPARE_PARTIAL_FLAG$3)) { + var objIsWrapped = objIsObj && hasOwnProperty$b.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty$b.call(other, '__wrapped__'); -var TAKEN_BY_OTHER_TYPE_ERR = 'You are trying to register an event already been taken by other type:'; + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; -// Create two WeakMap store as a private keys -var NB_EVENT_SERVICE_PRIVATE_STORE = new WeakMap(); -var NB_EVENT_SERVICE_PRIVATE_LAZY = new WeakMap(); - -/** - * generate a 32bit hash based on the function.toString() - * _from http://stackoverflow.com/questions/7616461/generate-a-hash-_from-string-in-javascript-jquery - * @param {string} s the converted to string function - * @return {string} the hashed function string - */ -function hashCode(s) { - return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0) + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack); + return equalObjects(object, other, bitmask, customizer, equalFunc, stack); } /** - * wrapper to make sure it string - * @param {*} input whatever - * @return {string} output + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Function} [customizer] The function to customize comparisons. + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ -function hashCode2Str(s) { - return hashCode(s) + '' +function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); } -/** - * Just check if a pattern is an RegExp object - * @param {*} pat whatever - * @return {boolean} false when its not - */ -function isRegExp(pat) { - return pat instanceof RegExp -} +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG$4 = 1, + COMPARE_UNORDERED_FLAG$2 = 2; /** - * check if its string - * @param {*} arg whatever - * @return {boolean} false when it's not + * The base implementation of `_.isMatch` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Array} matchData The property names, values, and compare flags to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. */ -function isString$2(arg) { - return typeof arg === 'string' -} +function baseIsMatch(object, source, matchData, customizer) { + var index = matchData.length, + length = index, + noCustomizer = !customizer; -/** - * Find from the array by matching the pattern - * @param {*} pattern a string or RegExp object - * @return {object} regex object or false when we can not id the input - */ -function getRegex(pattern) { - switch (true) { - case isRegExp(pattern) === true: - return pattern - case isString$2(pattern) === true: - return new RegExp(pattern) - default: - return false + if (object == null) { + return !length; } -} - -// 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(); -}; + object = Object(object); + while (index--) { + var data = matchData[index]; + if ((noCustomizer && data[2]) + ? data[1] !== object[data[0]] + : !(data[0] in object) + ) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], + objValue = object[key], + srcValue = data[1]; -var prototypeAccessors = { $queues: { configurable: true } }; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var stack = new Stack; + if (customizer) { + var result = customizer(objValue, srcValue, key, object, source, stack); + } + if (!(result === undefined + ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG$4 | COMPARE_UNORDERED_FLAG$2, customizer, stack) + : result + )) { + return false; + } + } + } + return true; +} /** - * start suspend - * @return {void} + * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` if suitable for strict + * equality comparisons, else `false`. */ -SuspendClass.prototype.$suspend = function $suspend () { - this.logger("---> SUSPEND ALL OPS <---"); - this.__suspend__(true); -}; +function isStrictComparable(value) { + return value === value && !isObject(value); +} /** - * release the queue - * @return {void} + * Gets the property names, values, and compare flags of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the match data of `object`. */ -SuspendClass.prototype.$release = function $release () { - this.logger("---> RELEASE SUSPENDED QUEUE <---"); - this.__suspend__(false); -}; +function getMatchData(object) { + var result = keys(object), + length = result.length; -/** - * 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() + while (length--) { + var key = result[length], + value = object[key]; + + result[length] = [key, value, isStrictComparable(value)]; } - throw new Error(("We expect a pattern variable to be string or RegExp, but we got \"" + (typeof regex) + "\" instead")) -}; + return result; +} /** - * 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 + * A specialized version of `matchesProperty` for source values suitable + * for strict equality comparisons, i.e. `===`. + * + * @private + * @param {string} key The key of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. */ -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 - } +function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + 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__ -}; + return object[key] === srcValue && + (srcValue !== undefined || (key in Object(object))); + }; +} /** - * a getter to get all the store queue - * @return {array} Set turn into Array before return + * The base implementation of `_.matches` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. */ -prototypeAccessors.$queues.get = function () { - var size = this.queueStore.size; - this.logger('($queues)', ("size: " + size)); - if (size > 0) { - return Array.from(this.queueStore) +function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + return matchesStrictComparable(matchData[0][0], matchData[0][1]); } - return [] -}; + return function(object) { + return object === source || baseIsMatch(object, source, matchData); + }; +} + +/** Used to match property names within property paths. */ +var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/; /** - * to set the suspend and check if it's boolean value - * @param {boolean} value to trigger + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. */ -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))) +function isKey(value, object) { + if (isArray(value)) { + return false; } -}; + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); +} + +/** Error message constants. */ +var FUNC_ERROR_TEXT = 'Expected a function'; /** - * Release the queue - * @return {int} size if any + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided, it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `clear`, `delete`, `get`, `has`, and `set`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoized function. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; + * + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; */ -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))); +function memoize(func, resolver) { + if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); } + var memoized = function() { + var args = arguments, + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; - return size -}; - -Object.defineProperties( SuspendClass.prototype, prototypeAccessors ); + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result) || cache; + return result; + }; + memoized.cache = new (memoize.Cache || MapCache); + return memoized; +} -// break up the main file because its getting way too long +// Expose `MapCache`. +memoize.Cache = MapCache; -var StoreService = /*@__PURE__*/(function (SuspendClass) { - function StoreService(config) { - if ( config === void 0 ) config = {}; +/** Used as the maximum memoize cache size. */ +var MAX_MEMOIZE_SIZE = 500; - SuspendClass.call(this); - if (config.logger && typeof config.logger === 'function') { - this.logger = config.logger; +/** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ +function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); } - this.keep = config.keep; - // for the $done setter - this.result = config.keep ? [] : null; - // we need to init the store first otherwise it could be a lot of checking later - this.normalStore = new Map(); - this.lazyStore = new Map(); - } + return key; + }); - if ( SuspendClass ) StoreService.__proto__ = SuspendClass; - StoreService.prototype = Object.create( SuspendClass && SuspendClass.prototype ); - StoreService.prototype.constructor = StoreService; + var cache = result.cache; + return result; +} - var prototypeAccessors = { normalStore: { configurable: true },lazyStore: { configurable: true } }; +/** Used to match property names within property paths. */ +var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; - /** - * validate the event name(s) - * @param {string[]} evt event name - * @return {boolean} true when OK - */ - StoreService.prototype.validateEvt = function validateEvt () { - var this$1 = this; - var evt = [], len = arguments.length; - while ( len-- ) evt[ len ] = arguments[ len ]; +/** Used to match backslashes in property paths. */ +var reEscapeChar = /\\(\\)?/g; - 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 - }; +/** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ +var stringToPath = memoizeCapped(function(string) { + var result = []; + if (string.charCodeAt(0) === 46 /* . */) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, subString) { + result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; +}); - /** - * Simple quick check on the two main parameters - * @param {string} evt event name - * @param {function} callback function to call - * @return {boolean} true when OK - */ - StoreService.prototype.validate = function validate (evt, callback) { - if (this.validateEvt(evt)) { - if (typeof callback === 'function') { - return true - } - } - throw new Error(("callback required to be function type! we got " + (typeof callback))) - }; +/** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @param {Object} [object] The object to query keys on. + * @returns {Array} Returns the cast property path array. + */ +function castPath(value, object) { + if (isArray(value)) { + return value; + } + return isKey(value, object) ? [value] : stringToPath(toString(value)); +} - /** - * Check if this type is correct or not added in V1.5.0 - * @param {string} type for checking - * @return {boolean} true on OK - */ - StoreService.prototype.validateType = function validateType (type) { - this.validateEvt(type); - var types = ['on', 'only', 'once', 'onlyOnce']; - return !!types.filter(function (t) { return type === t; }).length - }; +/** Used as references for various `Number` constants. */ +var INFINITY$1 = 1 / 0; - /** - * 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)); - }; +/** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ +function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY$1) ? '-0' : result; +} - /** - * Take the content out and remove it from store id by the name - * @param {string} evt event name - * @param {string} [storeName = lazyStore] name of store - * @return {object|boolean} content or false on not found - */ - StoreService.prototype.takeFromStore = function takeFromStore (evt, storeName) { - if ( storeName === void 0 ) storeName = 'lazyStore'; +/** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ +function baseGet(object, path) { + path = castPath(path, object); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; +} + +/** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ +function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; +} + +/** + * The base implementation of `_.hasIn` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ +function baseHasIn(object, key) { + return object != null && key in Object(object); +} + +/** + * Checks if `path` exists on `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @param {Function} hasFunc The function to check properties. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + */ +function hasPath(object, path, hasFunc) { + path = castPath(path, object); + + var index = -1, + length = path.length, + result = false; + + while (++index < length) { + var key = toKey(path[index]); + if (!(result = object != null && hasFunc(object, key))) { + break; + } + object = object[key]; + } + if (result || ++index != length) { + return result; + } + length = object == null ? 0 : object.length; + return !!length && isLength(length) && isIndex(key, length) && + (isArray(object) || isArguments(object)); +} + +/** + * Checks if `path` is a direct or inherited property of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.hasIn(object, 'a'); + * // => true + * + * _.hasIn(object, 'a.b'); + * // => true + * + * _.hasIn(object, ['a', 'b']); + * // => true + * + * _.hasIn(object, 'b'); + * // => false + */ +function hasIn(object, path) { + return object != null && hasPath(object, path, baseHasIn); +} + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG$5 = 1, + COMPARE_UNORDERED_FLAG$3 = 2; + +/** + * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. + * + * @private + * @param {string} path The path of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ +function baseMatchesProperty(path, srcValue) { + if (isKey(path) && isStrictComparable(srcValue)) { + return matchesStrictComparable(toKey(path), srcValue); + } + return function(object) { + var objValue = get(object, path); + return (objValue === undefined && objValue === srcValue) + ? hasIn(object, path) + : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG$5 | COMPARE_UNORDERED_FLAG$3); + }; +} + +/** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ +function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; +} + +/** + * A specialized version of `baseProperty` which supports deep paths. + * + * @private + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new accessor function. + */ +function basePropertyDeep(path) { + return function(object) { + return baseGet(object, path); + }; +} + +/** + * Creates a function that returns the value at `path` of a given object. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Util + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new accessor function. + * @example + * + * var objects = [ + * { 'a': { 'b': 2 } }, + * { 'a': { 'b': 1 } } + * ]; + * + * _.map(objects, _.property('a.b')); + * // => [2, 1] + * + * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b'); + * // => [1, 2] + */ +function property(path) { + return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path); +} + +/** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ +function baseIteratee(value) { + // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. + // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. + if (typeof value == 'function') { + return value; + } + if (value == null) { + return identity; + } + if (typeof value == 'object') { + return isArray(value) + ? baseMatchesProperty(value[0], value[1]) + : baseMatches(value); + } + return property(value); +} + +/** + * Creates an object with the same keys as `object` and values generated + * by running each own enumerable string keyed property of `object` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, key, object). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapKeys + * @example + * + * var users = { + * 'fred': { 'user': 'fred', 'age': 40 }, + * 'pebbles': { 'user': 'pebbles', 'age': 1 } + * }; + * + * _.mapValues(users, function(o) { return o.age; }); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + * + * // The `_.property` iteratee shorthand. + * _.mapValues(users, 'age'); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + */ +function mapValues(object, iteratee) { + var result = {}; + iteratee = baseIteratee(iteratee); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, key, iteratee(value, key, object)); + }); + return result; +} + +/** + * The opposite of `_.mapValues`; this method creates an object with the + * same values as `object` and keys generated by running each own enumerable + * string keyed property of `object` thru `iteratee`. The iteratee is invoked + * with three arguments: (value, key, object). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapValues + * @example + * + * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { + * return key + value; + * }); + * // => { 'a1': 1, 'b2': 2 } + */ +function mapKeys(object, iteratee) { + var result = {}; + iteratee = baseIteratee(iteratee); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, iteratee(value, key, object), value); + }); + return result; +} + +/** Error message constants. */ +var FUNC_ERROR_TEXT$1 = 'Expected a function'; + +/** + * Creates a function that negates the result of the predicate `func`. The + * `func` predicate is invoked with the `this` binding and arguments of the + * created function. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new negated function. + * @example + * + * function isEven(n) { + * return n % 2 == 0; + * } + * + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] + */ +function negate(predicate) { + if (typeof predicate != 'function') { + throw new TypeError(FUNC_ERROR_TEXT$1); + } + return function() { + var args = arguments; + switch (args.length) { + case 0: return !predicate.call(this); + case 1: return !predicate.call(this, args[0]); + case 2: return !predicate.call(this, args[0], args[1]); + case 3: return !predicate.call(this, args[0], args[1], args[2]); + } + return !predicate.apply(this, args); + }; +} + +/** + * The base implementation of `_.set`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ +function baseSet(object, path, value, customizer) { + if (!isObject(object)) { + return object; + } + path = castPath(path, object); + + var index = -1, + length = path.length, + lastIndex = length - 1, + nested = object; + + while (nested != null && ++index < length) { + var key = toKey(path[index]), + newValue = value; + + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = isObject(objValue) + ? objValue + : (isIndex(path[index + 1]) ? [] : {}); + } + } + assignValue(nested, key, newValue); + nested = nested[key]; + } + return object; +} + +/** + * The base implementation of `_.pickBy` without support for iteratee shorthands. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @param {Function} predicate The function invoked per property. + * @returns {Object} Returns the new object. + */ +function basePickBy(object, paths, predicate) { + var index = -1, + length = paths.length, + result = {}; + + while (++index < length) { + var path = paths[index], + value = baseGet(object, path); + + if (predicate(value, path)) { + baseSet(result, castPath(path, object), value); + } + } + return result; +} + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetSymbols$1 = Object.getOwnPropertySymbols; + +/** + * Creates an array of the own and inherited enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ +var getSymbolsIn = !nativeGetSymbols$1 ? stubArray : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototype(object); + } + return result; +}; + +/** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ +function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); +} + +/** + * Creates an object composed of the `object` properties `predicate` returns + * truthy for. The predicate is invoked with two arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pickBy(object, _.isNumber); + * // => { 'a': 1, 'c': 3 } + */ +function pickBy(object, predicate) { + if (object == null) { + return {}; + } + var props = arrayMap(getAllKeysIn(object), function(prop) { + return [prop]; + }); + predicate = baseIteratee(predicate); + return basePickBy(object, props, function(value, path) { + return predicate(value, path[0]); + }); +} + +/** + * The opposite of `_.pickBy`; this method creates an object composed of + * the own and inherited enumerable string keyed properties of `object` that + * `predicate` doesn't return truthy for. The predicate is invoked with two + * arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omitBy(object, _.isNumber); + * // => { 'b': '2' } + */ +function omitBy(object, predicate) { + return pickBy(object, negate(baseIteratee(predicate))); +} + +/** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ +function isEqual(value, other) { + return baseIsEqual(value, other); +} + +/** + * The base implementation of methods like `_.findKey` and `_.findLastKey`, + * without support for iteratee shorthands, which iterates over `collection` + * using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the found element or its key, else `undefined`. + */ +function baseFindKey(collection, predicate, eachFunc) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = key; + return false; + } + }); + return result; +} + +/** + * This method is like `_.find` except that it returns the key of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findKey(users, function(o) { return o.age < 40; }); + * // => 'barney' (iteration order is not guaranteed) + * + * // The `_.matches` iteratee shorthand. + * _.findKey(users, { 'age': 1, 'active': true }); + * // => 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findKey(users, 'active'); + * // => 'barney' + */ +function findKey(object, predicate) { + return baseFindKey(object, baseIteratee(predicate), baseForOwn); +} + +/** + * @param {array} arr Array for check + * @param {*} value target + * @return {boolean} true on successs + */ +var isInArray = function(arr, value) { + return !!arr.filter(function (a) { return a === value; }).length +}; + +var isObjectHasKey$1 = function(obj, key) { + var keys = Object.keys(obj); + return isInArray(keys, key) +}; + +// just not to make my head hurt +var isEmpty = function (value) { return !isNotEmpty(value); }; + +/** + * Map the alias to their key then grab their value over + * @param {object} config the user supplied config + * @param {object} appProps the default option map + * @return {object} the config keys replaced with the appProps key by the ALIAS + */ +function mapAliasConfigKeys(config, appProps) { + // need to do two steps + // 1. take key with alias key + var aliasMap = omitBy(appProps, function (value, k) { return !value[ALIAS_KEY]; } ); + if (isEqual(aliasMap, {})) { + return config; + } + return mapKeys(config, function (v, key) { return findKey(aliasMap, function (o) { return o.alias === key; }) || key; }) +} + +/** + * We only want to run the valdiation against the config (user supplied) value + * but keep the defaultOptions untouch + * @param {object} config configuraton supplied by user + * @param {object} appProps the default options map + * @return {object} the pristine values that will add back to the final output + */ +function preservePristineValues(config, appProps) { + // @BUG this will filter out those that is alias key + // we need to first map the alias keys back to their full key + var _config = mapAliasConfigKeys(config, appProps); + // take the default value out + var pristineValues = mapValues( + omitBy(appProps, function (value, key) { return isObjectHasKey$1(_config, key); }), + function (value) { return value.args; } + ); + // for testing the value + var checkAgainstAppProps = omitBy(appProps, function (value, key) { return !isObjectHasKey$1(_config, key); }); + // output + return { + pristineValues: pristineValues, + checkAgainstAppProps: checkAgainstAppProps, + config: _config // passing this correct values back + } +} + +/** + * This will take the value that is ONLY need to check + * @param {object} config that one + * @param {object} props map for creating checking + * @return {object} put that arg into the args + */ +function processConfigAction(config, props) { + // debugFn('processConfigAction', props) + // v.1.2.0 add checking if its mark optional and the value is empty then pass + return mapValues(props, function (value, key) { + var obj, obj$1; + + return ( + config[key] === undefined || (value[OPTIONAL_KEY] === true && isEmpty(config[key])) + ? merge({}, value, ( obj = {}, obj[KEY_WORD] = true, obj )) + : ( obj$1 = {}, obj$1[ARGS_KEY] = config[key], obj$1[TYPE_KEY] = value[TYPE_KEY], obj$1[OPTIONAL_KEY] = value[OPTIONAL_KEY] || false, obj$1[ENUM_KEY] = value[ENUM_KEY] || false, obj$1[CHECKER_KEY] = value[CHECKER_KEY] || false, obj$1 ) + ); + } + ) +} + +/** + * Quick transform + * @TODO we should only validate those that is pass from the config + * and pass through those values that is from the defaultOptions + * @param {object} opts that one + * @param {object} appProps mutation configuration options + * @return {object} put that arg into the args + */ +function prepareArgsForValidation(opts, appProps) { + var ref = preservePristineValues(opts, appProps); + var config = ref.config; + var pristineValues = ref.pristineValues; + var checkAgainstAppProps = ref.checkAgainstAppProps; + // output + return [ + processConfigAction(config, checkAgainstAppProps), + pristineValues + ] +} + +// breaking the whole thing up to see what cause the multiple calls issue + +// import debug from 'debug'; +// const debugFn = debug('jsonql-params-validator:options:validation') + +/** + * just make sure it returns an array to use + * @param {*} arg input + * @return {array} output + */ +var toArray$1 = function (arg) { return checkIsArray(arg) ? arg : [arg]; }; + +/** + * DIY in array + * @param {array} arr to check against + * @param {*} value to check + * @return {boolean} true on OK + */ +var inArray$1 = function (arr, value) { return ( + !!arr.filter(function (v) { return v === value; }).length +); }; + +/** + * break out to make the code easier to read + * @param {object} value to process + * @param {function} cb the validateSync + * @return {array} empty on success + */ +function validateHandler$1(value, cb) { + var obj; + + // cb is the validateSync methods + var args = [ + [ value[ARGS_KEY] ], + [( obj = {}, obj[TYPE_KEY] = toArray$1(value[TYPE_KEY]), obj[OPTIONAL_KEY] = value[OPTIONAL_KEY], obj )] + ]; + // debugFn('validateHandler', args) + return Reflect.apply(cb, null, args) +} + +/** + * Check against the enum value if it's provided + * @param {*} value to check + * @param {*} enumv to check against if it's not false + * @return {boolean} true on OK + */ +var enumHandler = function (value, enumv) { + if (checkIsArray(enumv)) { + return inArray$1(enumv, value) + } + return true +}; - 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 +/** + * Allow passing a function to check the value + * There might be a problem here if the function is incorrect + * and that will makes it hard to debug what is going on inside + * @TODO there could be a few feature add to this one under different circumstance + * @param {*} value to check + * @param {function} checker for checking + */ +var checkerHandler = function (value, checker) { + try { + return isFunction(checker) ? checker.apply(null, [value]) : false + } catch (e) { + return false + } +}; + +/** + * Taken out from the runValidaton this only validate the required values + * @param {array} args from the config2argsAction + * @param {function} cb validateSync + * @return {array} of configuration values + */ +function runValidationAction(cb) { + return function (value, key) { + // debugFn('runValidationAction', key, value) + if (value[KEY_WORD]) { + return value[ARGS_KEY] } - throw new Error(("\"" + storeName + "\" is not supported!")) - }; + var check = validateHandler$1(value, cb); + if (check.length) { + // log('runValidationAction', key, value) + throw new JsonqlTypeError(key, check) + } + if (value[ENUM_KEY] !== false && !enumHandler(value[ARGS_KEY], value[ENUM_KEY])) { + // log(ENUM_KEY, value[ENUM_KEY]) + throw new JsonqlEnumError(key) + } + if (value[CHECKER_KEY] !== false && !checkerHandler(value[ARGS_KEY], value[CHECKER_KEY])) { + // log(CHECKER_KEY, value[CHECKER_KEY]) + throw new JsonqlCheckerError(key) + } + return value[ARGS_KEY] + } +} + +/** + * @param {object} args from the config2argsAction + * @param {function} cb validateSync + * @return {object} of configuration values + */ +function runValidation(args, cb) { + var argsForValidate = args[0]; + var pristineValues = args[1]; + // turn the thing into an array and see what happen here + // debugFn('_args', argsForValidate) + var result = mapValues(argsForValidate, runValidationAction(cb)); + return merge(result, pristineValues) +} + +/// this is port back from the client to share across all projects + +// import debug from 'debug' +// const debugFn = debug('jsonql-params-validator:check-options-async') + +/** + * Quick transform + * @param {object} config that one + * @param {object} appProps mutation configuration options + * @return {object} put that arg into the args + */ +var configToArgs = function (config, appProps) { + return Promise.resolve( + prepareArgsForValidation(config, appProps) + ) +}; + +/** + * @param {object} config user provide configuration option + * @param {object} appProps mutation configuration options + * @param {object} constProps the immutable configuration options + * @param {function} cb the validateSync method + * @return {object} Promise resolve merge config object + */ +function checkOptionsAsync(config, appProps, constProps, cb) { + if ( config === void 0 ) config = {}; + + return configToArgs(config, appProps) + .then(function (args1) { return runValidation(args1, cb); }) + // next if every thing good then pass to final merging + .then(function (args2) { return merge({}, args2, constProps); }) +} + +// create function to construct the config entry so we don't need to keep building object +// import checkIsBoolean from '../boolean' +// import debug from 'debug'; +// const debugFn = debug('jsonql-params-validator:construct-config'); +/** + * @param {*} args value + * @param {string} type for value + * @param {boolean} [optional=false] + * @param {boolean|array} [enumv=false] + * @param {boolean|function} [checker=false] + * @return {object} config entry + */ +function constructConfig(args, type, optional, enumv, checker, alias) { + if ( optional === void 0 ) optional=false; + if ( enumv === void 0 ) enumv=false; + if ( checker === void 0 ) checker=false; + if ( alias === void 0 ) alias=false; + + var base = {}; + base[ARGS_KEY] = args; + base[TYPE_KEY] = type; + if (optional === true) { + base[OPTIONAL_KEY] = true; + } + if (checkIsArray(enumv)) { + base[ENUM_KEY] = enumv; + } + if (isFunction(checker)) { + base[CHECKER_KEY] = checker; + } + if (isString(alias)) { + base[ALIAS_KEY] = alias; + } + return base +} + +// export also create wrapper methods + +/** + * This has a different interface + * @param {*} value to supply + * @param {string|array} type for checking + * @param {object} params to map against the config check + * @param {array} params.enumv NOT enum + * @param {boolean} params.optional false then nothing + * @param {function} params.checker need more work on this one later + * @param {string} params.alias mostly for cmd + */ +var createConfig = function (value, type, params) { + if ( params === void 0 ) params = {}; + + // Note the enumv not ENUM + // const { enumv, optional, checker, alias } = params; + // let args = [value, type, optional, enumv, checker, alias]; + var o = params[OPTIONAL_KEY]; + var e = params[ENUM_KEY]; + var c = params[CHECKER_KEY]; + var a = params[ALIAS_KEY]; + return constructConfig.apply(null, [value, type, o, e, c, a]) +}; +/** + * construct the actual end user method, rename with prefix get since 1.5.2 + * @param {function} validateSync validation method + * @return {function} for performaning the actual valdiation + */ +var getCheckConfigAsync = function(validateSync) { /** - * This was part of the $get. We take it out - * so we could use a regex to remove more than one event - * @param {object} store the store to return from - * @param {string} evt event name - * @param {boolean} full return just the callback or everything - * @return {array|boolean} false when not found + * We recreate the method here to avoid the circlar import + * @param {object} config user supply configuration + * @param {object} appProps mutation options + * @param {object} [constantProps={}] optional: immutation options + * @return {object} all checked configuration */ - StoreService.prototype.findFromStore = function findFromStore (evt, store, full) { - if ( full === void 0 ) full = false; + return function(config, appProps, constantProps) { + if ( constantProps === void 0 ) constantProps= {}; + + return checkOptionsAsync(config, appProps, constantProps, validateSync) + } +}; + +// export +var isString$1 = checkIsString; +var validateAsync$1 = validateAsync; + +var createConfig$1 = createConfig; +// construct the final output 1.5.2 +var checkConfigAsync = getCheckConfigAsync(validateSync); + +// move the get logger stuff here + +// it does nothing +var dummyLogger = function () {}; + +/** + * re-use the debugOn prop to control this log method + * @param {object} opts configuration + * @return {function} the log function + */ +var getLogger = function (opts) { + var debugOn = opts.debugOn; + if (debugOn) { + return function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + Reflect.apply(console.info, console, ['[jsonql-ws-client-core]' ].concat( args)); + } + } + return dummyLogger +}; + +/** + * Make sure there is a log method + * @param {object} opts configuration + * @return {object} opts + */ +var getLogFn = function (opts) { + var log = opts.log; // 1.3.9 if we pass a log method here then we use this + if (!log || typeof log !== 'function') { + return getLogger(opts) + } + opts.log('---> getLogFn user supplied log function <---', opts); + return log +}; + +// group all the repetitive message here + +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(); + +/** + * generate a 32bit hash based on the function.toString() + * _from http://stackoverflow.com/questions/7616461/generate-a-hash-_from-string-in-javascript-jquery + * @param {string} s the converted to string function + * @return {string} the hashed function string + */ +function hashCode(s) { + return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0) +} - if (store.has(evt)) { - return Array - .from(store.get(evt)) - .map( function (l) { - if (full) { - return l - } - var key = l[0]; - var callback = l[1]; - return callback - }) - } - return false - }; +/** + * wrapper to make sure it string + * @param {*} input whatever + * @return {string} output + */ +function hashCode2Str(s) { + return hashCode(s) + '' +} - /** - * Similar to the findFromStore, but remove - * @param {string} evt event name - * @param {object} store the store to remove from - * @return {boolean} false when not found - */ - StoreService.prototype.removeFromStore = function removeFromStore (evt, store) { - if (store.has(evt)) { - this.logger('($off)', evt); - store.delete(evt); - return true - } - return false - }; +/** + * Just check if a pattern is an RegExp object + * @param {*} pat whatever + * @return {boolean} false when its not + */ +function isRegExp(pat) { + return pat instanceof RegExp +} - /** - * 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 ]; +/** + * check if its string + * @param {*} arg whatever + * @return {boolean} false when it's not + */ +function isString$2(arg) { + return typeof arg === 'string' +} - var fnSet; - if (store.has(evt)) { - this.logger(("(addToStore) \"" + evt + "\" existed")); - fnSet = store.get(evt); - } else { - this.logger(("(addToStore) create new Set for \"" + evt + "\"")); - // this is new - fnSet = new Set(); - } - // lazy only store 2 items - this is not the case in V1.6.0 anymore - // we need to check the first parameter is string or not - if (args.length > 2) { - if (Array.isArray(args[0])) { // lazy store - // check if this type of this event already register in the lazy store - var t = args[2]; - if (!this.checkTypeInLazyStore(evt, t)) { - fnSet.add(args); - } - } else { - if (!this.checkContentExist(args, fnSet)) { - this.logger("(addToStore) insert new", args); - fnSet.add(args); - } - } - } else { // add straight to lazy store - fnSet.add(args); - } - store.set(evt, fnSet); - return [store, fnSet.size] - }; +/** + * Find from the array by matching the pattern + * @param {*} pattern a string or RegExp object + * @return {object} regex object or false when we can not id the input + */ +function getRegex(pattern) { + switch (true) { + case isRegExp(pattern) === true: + return pattern + case isString$2(pattern) === true: + return new RegExp(pattern) + default: + return false + } +} - /** - * @param {array} args for compare - * @param {object} fnSet A Set to search from - * @return {boolean} true on exist - */ - StoreService.prototype.checkContentExist = function checkContentExist (args, fnSet) { - var list = Array.from(fnSet); - return !!list.filter(function (li) { - var hash = li[0]; - return hash === args[0] - }).length - }; +// making all the functionality on it's own - /** - * get the existing type to make sure no mix type add to the same store - * @param {string} evtName event name - * @param {string} type the type to check - * @return {boolean} true you can add, false then you can't add this type - */ - StoreService.prototype.checkTypeInStore = function checkTypeInStore (evtName, type) { - this.validateEvt(evtName, type); - var all = this.$get(evtName, true); - if (all === false) { - // pristine it means you can add - return true - } - // it should only have ONE type in ONE event store - return !all.filter(function (list) { - var t = list[3]; - return type !== t - }).length - }; +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(); +}; - /** - * This is checking just the lazy store because the structure is different - * therefore we need to use a new method to check it - */ - 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) { - var t = li[2]; - return t !== type - }).length - } - return false - }; +var prototypeAccessors = { $queues: { configurable: true } }; - /** - * wrapper to re-use the addToStore, - * V1.3.0 add extra check to see if this type can add to this evt - * @param {string} evt event name - * @param {string} type on or once - * @param {function} callback function - * @param {object} context the context the function execute in or null - * @return {number} size of the store - */ - StoreService.prototype.addToNormalStore = function addToNormalStore (evt, type, callback, context) { - if ( context === void 0 ) context = null; +/** + * start suspend + * @return {void} + */ +SuspendClass.prototype.$suspend = function $suspend () { + this.logger("---> SUSPEND ALL OPS <---"); + this.__suspend__(true); +}; - 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 - }; +/** + * release the queue + * @return {void} + */ +SuspendClass.prototype.$release = function $release () { + this.logger("---> RELEASE SUSPENDED QUEUE <---"); + this.__suspend__(false); +}; - /** - * Add to lazy store this get calls when the callback is not register yet - * so we only get a payload object or even nothing - * @param {string} evt event name - * @param {array} payload of arguments or empty if there is none - * @param {object} [context=null] the context the callback execute in - * @param {string} [type=false] register a type so no other type can add to this evt - * @return {number} size of the store - */ - StoreService.prototype.addToLazyStore = function addToLazyStore (evt, payload, context, type) { - if ( payload === void 0 ) payload = []; - if ( context === void 0 ) context = null; - if ( type === void 0 ) type = false; +/** + * 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")) +}; - // this is add in V1.6.0 - // when there is type then we will need to check if this already added in lazy store - // and no other type can add to this lazy store - var args = [this.lazyStore, evt, this.toArray(payload), context]; - if (type) { - args.push(type); - } - var ref = Reflect.apply(this.addToStore, this, args); - var _store = ref[0]; - var size = ref[1]; - this.lazyStore = _store; - this.logger(("(addToLazyStore) size: " + size)); - return size - }; +/** + * 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 ]; - /** - * make sure we store the argument correctly - * @param {*} arg could be array - * @return {array} make sured - */ - StoreService.prototype.toArray = function toArray (arg) { - return Array.isArray(arg) ? arg : [arg] - }; + 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__ +}; - /** - * setter to store the Set in private - * @param {object} obj a Set - */ - prototypeAccessors.normalStore.set = function (obj) { - NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj); - }; +/** + * 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 [] +}; - /** - * @return {object} Set object - */ - prototypeAccessors.normalStore.get = function () { - return NB_EVENT_SERVICE_PRIVATE_STORE.get(this) - }; +/** + * 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))) + } +}; - /** - * setter to store the Set in lazy store - * @param {object} obj a Set - */ - prototypeAccessors.lazyStore.set = function (obj) { - NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj); - }; +/** + * Release the queue + * @return {int} size if any + */ +SuspendClass.prototype.__release__ = function __release__ () { + var this$1 = this; - /** - * @return {object} the lazy store Set - */ - prototypeAccessors.lazyStore.get = function () { - return NB_EVENT_SERVICE_PRIVATE_LAZY.get(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))); + } - /** - * 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()) - }; + return size +}; - Object.defineProperties( StoreService.prototype, prototypeAccessors ); +Object.defineProperties( SuspendClass.prototype, prototypeAccessors ); - return StoreService; -}(SuspendClass)); +// break up the main file because its getting way too long -// The top level -// export -var EventService = /*@__PURE__*/(function (StoreService) { - function EventService(config) { +var StoreService = /*@__PURE__*/(function (SuspendClass) { + function StoreService(config) { if ( config === void 0 ) config = {}; - StoreService.call(this, config); + SuspendClass.call(this); + if (config.logger && typeof config.logger === 'function') { + this.logger = config.logger; + } + this.keep = config.keep; + // for the $done setter + this.result = config.keep ? [] : null; + // we need to init the store first otherwise it could be a lot of checking later + this.normalStore = new Map(); + this.lazyStore = new Map(); } - if ( StoreService ) EventService.__proto__ = StoreService; - EventService.prototype = Object.create( StoreService && StoreService.prototype ); - EventService.prototype.constructor = EventService; + if ( SuspendClass ) StoreService.__proto__ = SuspendClass; + StoreService.prototype = Object.create( SuspendClass && SuspendClass.prototype ); + StoreService.prototype.constructor = StoreService; - var prototypeAccessors = { $name: { configurable: true },is: { configurable: true },$done: { configurable: true } }; + var prototypeAccessors = { normalStore: { configurable: true },lazyStore: { configurable: true } }; /** - * logger function for overwrite + * validate the event name(s) + * @param {string[]} evt event name + * @return {boolean} true when OK */ - EventService.prototype.logger = function logger () {}; - - // for id if the instance is this class - prototypeAccessors.$name.get = function () { - return 'to1source-event' - }; + StoreService.prototype.validateEvt = function validateEvt () { + var this$1 = this; + var evt = [], len = arguments.length; + while ( len-- ) evt[ len ] = arguments[ len ]; - // take this down in the next release - prototypeAccessors.is.get = function () { - return this.$name + 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 }; - ////////////////////////// - // PUBLIC METHODS // - ////////////////////////// - /** - * Register your evt handler, note we don't check the type here, - * we expect you to be sensible and know what you are doing. - * @param {string} evt name of event - * @param {function} callback bind method --> if it's array or not - * @param {object} [context=null] to execute this call in - * @return {number} the size of the store + * Simple quick check on the two main parameters + * @param {string} evt event name + * @param {function} callback function to call + * @return {boolean} true when OK */ - EventService.prototype.$on = function $on (evt , callback , context) { - var this$1 = this; - if ( context === void 0 ) context = null; - - var type = 'on'; - this.validate(evt, callback); - // first need to check if this evt is in lazy store - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register first then call later - if (lazyStoreContent === false) { - this.logger(("($on) \"" + evt + "\" is not in lazy store")); - // @TODO we need to check if there was other listener to this - // event and are they the same type then we could solve that - // register the different type to the same event name - return this.addToNormalStore(evt, type, callback, context) - } - this.logger(("($on) " + evt + " found in lazy store")); - // this is when they call $trigger before register this callback - var size = 0; - lazyStoreContent.forEach(function (content) { - var payload = content[0]; - var ctx = content[1]; - var t = content[2]; - if (t && t !== type) { - throw new Error((TAKEN_BY_OTHER_TYPE_ERR + " " + t)) + StoreService.prototype.validate = function validate (evt, callback) { + if (this.validateEvt(evt)) { + if (typeof callback === 'function') { + return true } - this$1.logger("($on)", ("call run \"" + evt + "\"")); - this$1.run(callback, payload, context || ctx); - size += this$1.addToNormalStore(evt, type, callback, context || ctx); - }); - - this.logger(("($on) return size " + size)); - return size + } + throw new Error(("callback required to be function type! we got " + (typeof callback))) }; /** - * once only registered it once, there is no overwrite option here - * @NOTE change in v1.3.0 $once can add multiple listeners - * but once the event fired, it will remove this event (see $only) - * @param {string} evt name - * @param {function} callback to execute - * @param {object} [context=null] the handler execute in - * @return {boolean} result + * Check if this type is correct or not added in V1.5.0 + * @param {string} type for checking + * @return {boolean} true on OK */ - EventService.prototype.$once = function $once (evt , callback , context) { - if ( context === void 0 ) context = null; + StoreService.prototype.validateType = function validateType (type) { + this.validateEvt(type); + var types = ['on', 'only', 'once', 'onlyOnce']; + return !!types.filter(function (t) { return type === t; }).length + }; - this.validate(evt, callback); - var type = 'once'; - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register before call $trigger - var nStore = this.normalStore; - if (lazyStoreContent === false) { - this.logger(("($once) \"" + evt + "\" is not in the lazy store")); - // v1.3.0 $once now allow to add multiple listeners - return this.addToNormalStore(evt, type, callback, context) - } else { - // now this is the tricky bit - // there is a potential bug here that cause by the developer - // if they call $trigger first, the lazy won't know it's a once call - // so if in the middle they register any call with the same evt name - // then this $once call will be fucked - add this to the documentation - this.logger('($once)', lazyStoreContent); - var list = Array.from(lazyStoreContent); - // should never have more than 1 - var ref = list[0]; - var payload = ref[0]; - var ctx = ref[1]; - var t = ref[2]; - if (t && t !== type) { - throw new Error((TAKEN_BY_OTHER_TYPE_ERR + " " + t)) + /** + * 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)); + }; + + /** + * Take the content out and remove it from store id by the name + * @param {string} evt event name + * @param {string} [storeName = lazyStore] name of store + * @return {object|boolean} content or false on not found + */ + StoreService.prototype.takeFromStore = function takeFromStore (evt, storeName) { + if ( storeName === void 0 ) storeName = 'lazyStore'; + + var store = this[storeName]; // it could be empty at this point + if (store) { + this.logger('(takeFromStore)', storeName, store); + if (store.has(evt)) { + var content = store.get(evt); + this.logger(("(takeFromStore) has \"" + evt + "\""), content); + store.delete(evt); + return content } - this.logger('($once)', ("call run \"" + evt + "\"")); - this.run(callback, payload, context || ctx); - // remove this evt from store - this.$off(evt); + return false } + throw new Error(("\"" + storeName + "\" is not supported!")) }; /** - * This one event can only bind one callbackback + * This was part of the $get. We take it out + * so we could use a regex to remove more than one event + * @param {object} store the store to return from * @param {string} evt event name - * @param {function} callback event handler - * @param {object} [context=null] the context the event handler execute in - * @return {boolean} true bind for first time, false already existed + * @param {boolean} full return just the callback or everything + * @return {array|boolean} false when not found */ - EventService.prototype.$only = function $only (evt, callback, context) { - var this$1 = this; - if ( context === void 0 ) context = null; + StoreService.prototype.findFromStore = function findFromStore (evt, store, full) { + if ( full === void 0 ) full = false; - 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); + if (store.has(evt)) { + return Array + .from(store.get(evt)) + .map( function (l) { + if (full) { + return l + } + var key = l[0]; + var callback = l[1]; + return callback + }) } - if (lazyStoreContent !== false) { - // there are data store in lazy store - this.logger(("($only) \"" + evt + "\" found data in lazy store to execute")); - var list = Array.from(lazyStoreContent); - // $only allow to trigger this multiple time on the single handler - list.forEach( function (li) { - var payload = li[0]; - var ctx = li[1]; - var t = li[2]; - if (t && t !== 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 false + }; + + /** + * Similar to the findFromStore, but remove + * @param {string} evt event name + * @param {object} store the store to remove from + * @return {boolean} false when not found + */ + StoreService.prototype.removeFromStore = function removeFromStore (evt, store) { + if (store.has(evt)) { + this.logger('($off)', evt); + store.delete(evt); + return true } - return added + return false }; /** - * $only + $once this is because I found a very subtile bug when we pass a - * resolver, rejecter - and it never fire because that's OLD added in v1.4.0 + * 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 {function} callback to call later - * @param {object} [context=null] exeucte context - * @return {void} + * @param {spread} args because the lazy store and normal store store different things + * @return {array} store and the size of the store */ - EventService.prototype.$onlyOnce = function $onlyOnce (evt, callback, context) { - if ( context === void 0 ) context = null; + StoreService.prototype.addToStore = function addToStore (store, evt) { + var args = [], len = arguments.length - 2; + while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; - 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); + var fnSet; + if (store.has(evt)) { + this.logger(("(addToStore) \"" + evt + "\" existed")); + fnSet = store.get(evt); + } else { + this.logger(("(addToStore) create new Set for \"" + evt + "\"")); + // this is new + fnSet = new Set(); } - if (lazyStoreContent !== false) { - // there are data store in lazy store - this.logger('($onlyOnce)', lazyStoreContent); - var list = Array.from(lazyStoreContent); - // should never have more than 1 - var ref = list[0]; - var payload = ref[0]; - var ctx = ref[1]; - var t = ref[2]; - if (t && t !== 'onlyOnce') { - throw new Error((TAKEN_BY_OTHER_TYPE_ERR + " " + t)) + // lazy only store 2 items - this is not the case in V1.6.0 anymore + // we need to check the first parameter is string or not + if (args.length > 2) { + if (Array.isArray(args[0])) { // lazy store + // check if this type of this event already register in the lazy store + var t = args[2]; + if (!this.checkTypeInLazyStore(evt, t)) { + fnSet.add(args); + } + } else { + if (!this.checkContentExist(args, fnSet)) { + this.logger("(addToStore) insert new", args); + fnSet.add(args); + } } - this.logger(("($onlyOnce) call run \"" + evt + "\"")); - this.run(callback, payload, context || ctx); - // remove this evt from store - this.$off(evt); + } else { // add straight to lazy store + fnSet.add(args); } - return added + store.set(evt, fnSet); + return [store, fnSet.size] }; /** - * This is a shorthand of $off + $on added in V1.5.0 - * @param {string} evt event name - * @param {function} callback to exeucte - * @param {object} [context = null] or pass a string as type - * @param {string} [type=on] what type of method to replace - * @return {*} + * @param {array} args for compare + * @param {object} fnSet A Set to search from + * @return {boolean} true on exist */ - EventService.prototype.$replace = function $replace (evt, callback, context, type) { - if ( context === void 0 ) context = null; - if ( type === void 0 ) type = 'on'; + StoreService.prototype.checkContentExist = function checkContentExist (args, fnSet) { + var list = Array.from(fnSet); + return !!list.filter(function (li) { + var hash = li[0]; + return hash === args[0] + }).length + }; - if (this.validateType(type)) { - this.$off(evt); - var method = this['$' + type]; - this.logger("($replace)", evt, callback); - return Reflect.apply(method, this, [evt, callback, context]) + /** + * get the existing type to make sure no mix type add to the same store + * @param {string} evtName event name + * @param {string} type the type to check + * @return {boolean} true you can add, false then you can't add this type + */ + StoreService.prototype.checkTypeInStore = function checkTypeInStore (evtName, type) { + this.validateEvt(evtName, type); + var all = this.$get(evtName, true); + if (all === false) { + // pristine it means you can add + return true } - throw new Error((type + " is not supported!")) + // it should only have ONE type in ONE event store + return !all.filter(function (list) { + var t = list[3]; + return type !== t + }).length }; /** - * trigger the event - * @param {string} evt name NOT allow array anymore! - * @param {mixed} [payload = []] pass to fn - * @param {object|string} [context = null] overwrite what stored - * @param {string} [type=false] if pass this then we need to add type to store too - * @return {number} if it has been execute how many times + * This is checking just the lazy store because the structure is different + * therefore we need to use a new method to check it */ - EventService.prototype.$trigger = function $trigger (evt , payload , context, type) { - if ( payload === void 0 ) payload = []; - if ( context === void 0 ) context = null; - if ( type === void 0 ) type = false; - - this.validateEvt(evt); - var found = 0; - // first check the normal store - var nStore = this.normalStore; - this.logger('($trigger) normalStore', nStore); - if (nStore.has(evt)) { - this.logger(("($trigger) \"" + evt + "\" found")); - // @1.8.0 to add the suspend queue - var added = this.$queue(evt, payload, context, type); - if (added) { - this.logger(("($trigger) Currently suspended \"" + evt + "\" added to queue, nothing executed. Exit now.")); - return false // not executed - } - var nSet = Array.from(nStore.get(evt)); - var ctn = nSet.length; - var hasOnce = false; - for (var i=0; i < ctn; ++i) { - ++found; - // this.logger('found', found) - var ref = nSet[i]; - var _ = ref[0]; - var callback = ref[1]; - var ctx = ref[2]; - var type$1 = ref[3]; - this.logger(("($trigger) call run for " + evt)); - this.run(callback, payload, context || ctx); - if (type$1 === 'once' || type$1 === 'onlyOnce') { - hasOnce = true; - } - } - if (hasOnce) { - nStore.delete(evt); - } - return found + 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) { + var t = li[2]; + return t !== type + }).length } - // now this is not register yet - this.addToLazyStore(evt, payload, context, type); - return found + return false }; /** - * this is an alias to the $trigger - * @NOTE breaking change in V1.6.0 we swap the parameter aroun - * @NOTE breaking change: v1.9.1 it return an function to accept the params as spread + * wrapper to re-use the addToStore, + * V1.3.0 add extra check to see if this type can add to this evt * @param {string} evt event name - * @param {string} type of call - * @param {object} context what context callback execute in - * @return {*} from $trigger + * @param {string} type on or once + * @param {function} callback function + * @param {object} context the context the function execute in or null + * @return {number} size of the store */ - EventService.prototype.$call = function $call (evt, type, context) { - if ( type === void 0 ) type = false; + StoreService.prototype.addToNormalStore = function addToNormalStore (evt, type, callback, context) { if ( context === void 0 ) context = null; - var ctx = this; - - return function () { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - var _args = [evt, args, context, type]; - return Reflect.apply(ctx.$trigger, ctx, _args) + 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 }; /** - * remove the evt from all the stores - * @param {string} evt name - * @return {boolean} true actually delete something + * Add to lazy store this get calls when the callback is not register yet + * so we only get a payload object or even nothing + * @param {string} evt event name + * @param {array} payload of arguments or empty if there is none + * @param {object} [context=null] the context the callback execute in + * @param {string} [type=false] register a type so no other type can add to this evt + * @return {number} size of the store */ - EventService.prototype.$off = function $off (evt) { - var this$1 = this; - - // @TODO we will allow a regex pattern to mass remove event - this.validateEvt(evt); - var stores = [ this.lazyStore, this.normalStore ]; + StoreService.prototype.addToLazyStore = function addToLazyStore (evt, payload, context, type) { + if ( payload === void 0 ) payload = []; + if ( context === void 0 ) context = null; + if ( type === void 0 ) type = false; - return !!stores - .filter(function (store) { return store.has(evt); }) - .map(function (store) { return this$1.removeFromStore(evt, store); }) - .length + // this is add in V1.6.0 + // when there is type then we will need to check if this already added in lazy store + // and no other type can add to this lazy store + var args = [this.lazyStore, evt, this.toArray(payload), context]; + if (type) { + args.push(type); + } + var ref = Reflect.apply(this.addToStore, this, args); + var _store = ref[0]; + var size = ref[1]; + this.lazyStore = _store; + this.logger(("(addToLazyStore) size: " + size)); + return size }; /** - * return all the listener bind to that event name - * @param {string} evtName event name - * @param {boolean} [full=false] if true then return the entire content - * @return {array|boolean} listerner(s) or false when not found + * make sure we store the argument correctly + * @param {*} arg could be array + * @return {array} make sured */ - EventService.prototype.$get = function $get (evt, full) { - if ( full === void 0 ) full = false; - - // @TODO should we allow the same Regex to search for all? - this.validateEvt(evt); - var store = this.normalStore; - return this.findFromStore(evt, store, full) + StoreService.prototype.toArray = function toArray (arg) { + return Array.isArray(arg) ? arg : [arg] }; /** - * store the return result from the run - * @param {*} value whatever return from callback + * setter to store the Set in private + * @param {object} obj a Set */ - prototypeAccessors.$done.set = function (value) { - this.logger('($done) set value: ', value); - if (this.keep) { - this.result.push(value); - } else { - this.result = value; - } + prototypeAccessors.normalStore.set = function (obj) { + NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj); }; /** - * @TODO is there any real use with the keep prop? - * getter for $done - * @return {*} whatever last store result + * @return {object} Set object */ - prototypeAccessors.$done.get = function () { - this.logger('($done) get result:', this.result); - if (this.keep) { - return this.result[this.result.length - 1] - } - return this.result + prototypeAccessors.normalStore.get = function () { + return NB_EVENT_SERVICE_PRIVATE_STORE.get(this) }; /** - * Take a look inside the stores - * @param {number|null} idx of the store, null means all - * @return {void} + * setter to store the Set in lazy store + * @param {object} obj a Set */ - EventService.prototype.$debug = function $debug (idx) { - var this$1 = this; - if ( idx === void 0 ) idx = null; - - var names = ['lazyStore', 'normalStore']; - var stores = [this.lazyStore, this.normalStore]; - if (stores[idx]) { - this.logger(names[idx], stores[idx]); - } else { - stores.map(function (store, i) { - this$1.logger(names[i], store); - }); - } + prototypeAccessors.lazyStore.set = function (obj) { + NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj); }; - Object.defineProperties( EventService.prototype, prototypeAccessors ); - - return EventService; -}(StoreService)); - -// default - -// this will generate a event emitter and will be use everywhere -// create a clone version so we know which one we actually is using -var JsonqlWsEvt = /*@__PURE__*/(function (EventEmitterClass) { - function JsonqlWsEvt(logger) { - if (typeof logger !== 'function') { - throw new Error("Just die here the logger is not a function!") - } - logger("---> Create a new EventEmitter <---"); - // this ee will always come with the logger - // because we should take the ee from the configuration - EventEmitterClass.call(this, { logger: logger }); - } - - if ( EventEmitterClass ) JsonqlWsEvt.__proto__ = EventEmitterClass; - JsonqlWsEvt.prototype = Object.create( EventEmitterClass && EventEmitterClass.prototype ); - JsonqlWsEvt.prototype.constructor = JsonqlWsEvt; - - var prototypeAccessors = { name: { configurable: true } }; + /** + * @return {object} the lazy store Set + */ + prototypeAccessors.lazyStore.get = function () { + return NB_EVENT_SERVICE_PRIVATE_LAZY.get(this) + }; - prototypeAccessors.name.get = function () { - return 'jsonql-ws-client-core' + /** + * 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( JsonqlWsEvt.prototype, prototypeAccessors ); + Object.defineProperties( StoreService.prototype, prototypeAccessors ); - return JsonqlWsEvt; -}(EventService)); + return StoreService; +}(SuspendClass)); -/** - * getting the event emitter - * @param {object} opts configuration - * @return {object} the event emitter instance - */ -var getEventEmitter = function (opts) { - var log = opts.log; - var eventEmitter = opts.eventEmitter; - - if (eventEmitter) { - log("eventEmitter is:", eventEmitter.name); - return eventEmitter - } - - return new JsonqlWsEvt( opts.log ) -}; +// The top level +// export +var EventService = /*@__PURE__*/(function (StoreService) { + function EventService(config) { + if ( config === void 0 ) config = {}; -// bunch of generic helpers + StoreService.call(this, config); + } -/** - * DIY in Array - * @param {array} arr to check from - * @param {*} value to check against - * @return {boolean} true on found - */ -var inArray$1 = function (arr, value) { return !!arr.filter(function (a) { return a === value; }).length; }; + if ( StoreService ) EventService.__proto__ = StoreService; + EventService.prototype = Object.create( StoreService && StoreService.prototype ); + EventService.prototype.constructor = EventService; -// quick and dirty to turn non array to array -var toArray$1 = function (arg) { return isArray(arg) ? arg : [arg]; }; + var prototypeAccessors = { $name: { configurable: true },is: { configurable: true },$done: { configurable: true } }; -/** - * @param {object} obj for search - * @param {string} key target - * @return {boolean} true on success - */ -var isObjectHasKey$1 = function(obj, key) { - try { - var keys = Object.keys(obj); - return inArray$1(keys, key) - } catch(e) { - // @BUG when the obj is not an OBJECT we got some weird output - return false - } -}; + /** + * logger function for overwrite + */ + EventService.prototype.logger = function logger () {}; -/** - * create a event name - * @param {string[]} args - * @return {string} event name for use - */ -var createEvt = function () { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; + // for id if the instance is this class + prototypeAccessors.$name.get = function () { + return 'to1source-event' + }; - return args.join('_'); -}; + // take this down in the next release + prototypeAccessors.is.get = function () { + return this.$name + }; -/** - * Simple check if the prop is function - * @param {*} prop input - * @return {boolean} true on success - */ -var isFunc = function (prop) { - if (typeof prop === 'function') { - return true; - } - console.error(("Expect to be Function type! Got " + (typeof prop))); -}; + ////////////////////////// + // PUBLIC METHODS // + ////////////////////////// -// generic placeholder function -var nil = function () { return false; }; + /** + * Register your evt handler, note we don't check the type here, + * we expect you to be sensible and know what you are doing. + * @param {string} evt name of event + * @param {function} callback bind method --> if it's array or not + * @param {object} [context=null] to execute this call in + * @return {number} the size of the store + */ + EventService.prototype.$on = function $on (evt , callback , context) { + var this$1 = this; + if ( context === void 0 ) context = null; -/** - * using just the map reduce to chain multiple functions together - * @param {function} mainFn the init function - * @param {array} moreFns as many as you want to take the last value and return a new one - * @return {function} accept value for the mainFn - */ -var chainFns = function (mainFn) { - var moreFns = [], len = arguments.length - 1; - while ( len-- > 0 ) moreFns[ len ] = arguments[ len + 1 ]; + var type = 'on'; + this.validate(evt, callback); + // first need to check if this evt is in lazy store + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register first then call later + if (lazyStoreContent === false) { + this.logger(("($on) \"" + evt + "\" is not in lazy store")); + // @TODO we need to check if there was other listener to this + // event and are they the same type then we could solve that + // register the different type to the same event name + return this.addToNormalStore(evt, type, callback, context) + } + this.logger(("($on) " + evt + " found in lazy store")); + // this is when they call $trigger before register this callback + var size = 0; + lazyStoreContent.forEach(function (content) { + var payload = content[0]; + var ctx = content[1]; + var t = content[2]; + if (t && t !== type) { + throw new Error((TAKEN_BY_OTHER_TYPE_ERR + " " + t)) + } + this$1.logger("($on)", ("call run \"" + evt + "\"")); + this$1.run(callback, payload, context || ctx); + size += this$1.addToNormalStore(evt, type, callback, context || ctx); + }); - return ( - function () { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; + this.logger(("($on) return size " + size)); + return size + }; - return ( - moreFns.reduce(function (value, nextFn) { return ( - // change here to check if the return value is array then we spread it - Reflect.apply(nextFn, null, toArray$1(value)) - ); }, Reflect.apply(mainFn, null, args)) - ); - } -); -}; + /** + * once only registered it once, there is no overwrite option here + * @NOTE change in v1.3.0 $once can add multiple listeners + * but once the event fired, it will remove this event (see $only) + * @param {string} evt name + * @param {function} callback to execute + * @param {object} [context=null] the handler execute in + * @return {boolean} result + */ + EventService.prototype.$once = function $once (evt , callback , context) { + if ( context === void 0 ) context = null; -/** - * this is essentially the same as the injectToFn - * but this will not allow overwrite and set the setter and getter - * @param {object} obj to get injected - * @param {string} name of the property - * @param {function} setter for set - * @param {function} [getter=null] for get default return null fn - * @return {object} the injected obj - */ -function objDefineProps(obj, name, setter, getter) { - if ( getter === void 0 ) getter = null; + this.validate(evt, callback); + var type = 'once'; + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register before call $trigger + var nStore = this.normalStore; + if (lazyStoreContent === false) { + this.logger(("($once) \"" + evt + "\" is not in the lazy store")); + // v1.3.0 $once now allow to add multiple listeners + return this.addToNormalStore(evt, type, callback, context) + } else { + // now this is the tricky bit + // there is a potential bug here that cause by the developer + // if they call $trigger first, the lazy won't know it's a once call + // so if in the middle they register any call with the same evt name + // then this $once call will be fucked - add this to the documentation + this.logger('($once)', lazyStoreContent); + var list = Array.from(lazyStoreContent); + // should never have more than 1 + var ref = list[0]; + var payload = ref[0]; + var ctx = ref[1]; + var t = ref[2]; + if (t && t !== type) { + throw new Error((TAKEN_BY_OTHER_TYPE_ERR + " " + t)) + } + this.logger('($once)', ("call run \"" + evt + "\"")); + this.run(callback, payload, context || ctx); + // remove this evt from store + this.$off(evt); + } + }; - if (Object.getOwnPropertyDescriptor(obj, name) === undefined) { - Object.defineProperty(obj, name, { - set: setter, - get: getter === null ? function() { return null; } : getter - }); - } - return obj -} + /** + * This one event can only bind one callbackback + * @param {string} evt event name + * @param {function} callback event handler + * @param {object} [context=null] the context the event handler execute in + * @return {boolean} true bind for first time, false already existed + */ + EventService.prototype.$only = function $only (evt, callback, context) { + var this$1 = this; + if ( context === void 0 ) context = null; -/** - * check if the object has name property - * @param {object} obj the object to check - * @param {string} name the prop name - * @return {*} the value or undefined - */ -function objHasProp(obj, name) { - var prop = Object.getOwnPropertyDescriptor(obj, name); - return prop !== undefined && prop.value ? prop.value : prop -} + 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); + } + if (lazyStoreContent !== false) { + // there are data store in lazy store + this.logger(("($only) \"" + evt + "\" found data in lazy store to execute")); + var list = Array.from(lazyStoreContent); + // $only allow to trigger this multiple time on the single handler + list.forEach( function (li) { + var payload = li[0]; + var ctx = li[1]; + var t = li[2]; + if (t && t !== 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 + }; -/** - * After the user login we will use this Object.define add a new property - * to the resolver with the decoded user data - * @param {function} resolver target resolver - * @param {string} name the name of the object to get inject also for checking - * @param {object} data to inject into the function static interface - * @param {boolean} [overwrite=false] if we want to overwrite the existing data - * @return {function} added property resolver - */ -function injectToFn(resolver, name, data, overwrite) { - if ( overwrite === void 0 ) overwrite = false; + /** + * $only + $once this is because I found a very subtile bug when we pass a + * resolver, rejecter - and it never fire because that's OLD added in v1.4.0 + * @param {string} evt event name + * @param {function} callback to call later + * @param {object} [context=null] exeucte context + * @return {void} + */ + EventService.prototype.$onlyOnce = function $onlyOnce (evt, callback, context) { + if ( context === void 0 ) context = null; - var check = objHasProp(resolver, name); - if (overwrite === false && check !== undefined) { - // console.info(`NOT INJECTED`) - return resolver - } - /* this will throw error! @TODO how to remove props? - if (overwrite === true && check !== undefined) { - delete resolver[name] // delete this property - } - */ - // console.info(`INJECTED`) - Object.defineProperty(resolver, name, { - value: data, - writable: overwrite // if its set to true then we should able to overwrite it - }); + 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); + } + if (lazyStoreContent !== false) { + // there are data store in lazy store + this.logger('($onlyOnce)', lazyStoreContent); + var list = Array.from(lazyStoreContent); + // should never have more than 1 + var ref = list[0]; + var payload = ref[0]; + var ctx = ref[1]; + var t = ref[2]; + if (t && t !== 'onlyOnce') { + throw new Error((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); + } + return added + }; - return resolver -} + /** + * This is a shorthand of $off + $on added in V1.5.0 + * @param {string} evt event name + * @param {function} callback to exeucte + * @param {object} [context = null] or pass a string as type + * @param {string} [type=on] what type of method to replace + * @return {*} + */ + EventService.prototype.$replace = function $replace (evt, callback, context, type) { + if ( context === void 0 ) context = null; + if ( type === void 0 ) type = 'on'; -// split the contract into the node side and the generic side -/** - * Check if the json is a contract file or not - * @param {object} contract json object - * @return {boolean} true - */ -function checkIsContract(contract) { - return isPlainObject(contract) - && ( - isObjectHasKey$1(contract, QUERY_NAME) - || isObjectHasKey$1(contract, MUTATION_NAME) - || isObjectHasKey$1(contract, SOCKET_NAME) - ) -} + 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!")) + }; -/** - * Wrapper method that check if it's contract then return the contract or false - * @param {object} contract the object to check - * @return {boolean | object} false when it's not - */ -function isContract(contract) { - return checkIsContract(contract) ? contract : false -} + /** + * trigger the event + * @param {string} evt name NOT allow array anymore! + * @param {mixed} [payload = []] pass to fn + * @param {object|string} [context = null] overwrite what stored + * @param {string} [type=false] if pass this then we need to add type to store too + * @return {number} if it has been execute how many times + */ + EventService.prototype.$trigger = function $trigger (evt , payload , context, type) { + if ( payload === void 0 ) payload = []; + if ( context === void 0 ) context = null; + if ( type === void 0 ) type = false; -/** - * Ported from jsonql-params-validator but different - * if we don't find the socket part then return false - * @param {object} contract the contract object - * @return {object|boolean} false on failed - */ -function extractSocketPart(contract) { - if (isObjectHasKey$1(contract, SOCKET_NAME)) { - return contract[SOCKET_NAME] - } - return false -} + this.validateEvt(evt); + var found = 0; + // first check the normal store + var nStore = this.normalStore; + this.logger('($trigger) normalStore', nStore); + if (nStore.has(evt)) { + this.logger(("($trigger) \"" + evt + "\" found")); + // @1.8.0 to add the suspend queue + var added = this.$queue(evt, payload, context, type); + if (added) { + this.logger(("($trigger) Currently suspended \"" + evt + "\" added to queue, nothing executed. Exit now.")); + return false // not executed + } + var nSet = Array.from(nStore.get(evt)); + var ctn = nSet.length; + var hasOnce = false; + for (var i=0; i < ctn; ++i) { + ++found; + // this.logger('found', found) + var ref = nSet[i]; + var _ = ref[0]; + var callback = ref[1]; + var ctx = ref[2]; + var type$1 = ref[3]; + this.logger(("($trigger) call run for " + evt)); + this.run(callback, payload, context || ctx); + if (type$1 === 'once' || type$1 === 'onlyOnce') { + hasOnce = true; + } + } + if (hasOnce) { + nStore.delete(evt); + } + return found + } + // now this is not register yet + this.addToLazyStore(evt, payload, context, type); + return found + }; -/** - * @param {boolean} sec return in second or not - * @return {number} timestamp - */ -var timestamp = function (sec) { - if ( sec === void 0 ) sec = false; + /** + * this is an alias to the $trigger + * @NOTE breaking change in V1.6.0 we swap the parameter aroun + * @NOTE breaking change: v1.9.1 it return an function to accept the params as spread + * @param {string} evt event name + * @param {string} type of call + * @param {object} context what context callback execute in + * @return {*} from $trigger + */ + EventService.prototype.$call = function $call (evt, type, context) { + if ( type === void 0 ) type = false; + if ( context === void 0 ) context = null; - var time = Date.now(); - return sec ? Math.floor( time / 1000 ) : time -}; + var ctx = this; -// ported from jsonql-params-validator + return function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; -/** - * @param {*} args arguments to send - *@return {object} formatted payload - */ -var formatPayload = function (args) { - var obj; + var _args = [evt, args, context, type]; + return Reflect.apply(ctx.$trigger, ctx, _args) + } + }; - return ( - ( obj = {}, obj[QUERY_ARG_NAME] = args, obj ) -); -}; + /** + * remove the evt from all the stores + * @param {string} evt name + * @return {boolean} true actually delete something + */ + EventService.prototype.$off = function $off (evt) { + var this$1 = this; -/** - * wrapper method to add the timestamp as well - * @param {string} resolverName - * @param {*} payload - * @return {object} delierable - */ -function createDeliverable(resolverName, payload) { - var obj; + // @TODO we will allow a regex pattern to mass remove event + this.validateEvt(evt); + var stores = [ this.lazyStore, this.normalStore ]; - return ( obj = {}, obj[resolverName] = payload, obj[TIMESTAMP_PARAM_NAME] = [ timestamp() ], obj ) -} + return !!stores + .filter(function (store) { return store.has(evt); }) + .map(function (store) { return this$1.removeFromStore(evt, store); }) + .length + }; -/** - * @param {string} resolverName name of function - * @param {array} [args=[]] from the ...args - * @param {boolean} [jsonp = false] add v1.3.0 to koa - * @return {object} formatted argument - */ -function createQuery(resolverName, args, jsonp) { - if ( args === void 0 ) args = []; - if ( jsonp === void 0 ) jsonp = false; + /** + * return all the listener bind to that event name + * @param {string} evtName event name + * @param {boolean} [full=false] if true then return the entire content + * @return {array|boolean} listerner(s) or false when not found + */ + EventService.prototype.$get = function $get (evt, full) { + if ( full === void 0 ) full = false; - if (isString(resolverName) && isArray(args)) { - var payload = formatPayload(args); - if (jsonp === true) { - return payload - } - return createDeliverable(resolverName, payload) - } - throw new JsonqlValidationError("[createQuery] expect resolverName to be string and args to be array!", { resolverName: resolverName, args: args }) -} + // @TODO should we allow the same Regex to search for all? + this.validateEvt(evt); + var store = this.normalStore; + return this.findFromStore(evt, store, full) + }; -/** - * string version of the createQuery - * @return {string} - */ -function createQueryStr(resolverName, args, jsonp) { - if ( args === void 0 ) args = []; - if ( jsonp === void 0 ) jsonp = false; + /** + * store the return result from the run + * @param {*} value whatever return from callback + */ + prototypeAccessors.$done.set = function (value) { + this.logger('($done) set value: ', value); + if (this.keep) { + this.result.push(value); + } else { + this.result = value; + } + }; - return JSON.stringify(createQuery(resolverName, args, jsonp)) -} + /** + * @TODO is there any real use with the keep prop? + * getter for $done + * @return {*} whatever last store result + */ + prototypeAccessors.$done.get = function () { + this.logger('($done) get result:', this.result); + if (this.keep) { + return this.result[this.result.length - 1] + } + return this.result + }; -// take out all the namespace related methods in one place for easy to find -var SOCKET_NOT_FOUND_ERR = "socket not found in contract!"; -var SIZE = 'size'; + /** + * Take a look inside the stores + * @param {number|null} idx of the store, null means all + * @return {void} + */ + EventService.prototype.$debug = function $debug (idx) { + var this$1 = this; + if ( idx === void 0 ) idx = null; -/** - * create the group using publicNamespace when there is only public - * @param {object} socket from contract - * @param {string} publicNamespace - */ -function groupPublicNamespace(socket, publicNamespace) { - var obj; + var names = ['lazyStore', 'normalStore']; + var stores = [this.lazyStore, this.normalStore]; + if (stores[idx]) { + this.logger(names[idx], stores[idx]); + } else { + stores.map(function (store, i) { + this$1.logger(names[i], store); + }); + } + }; - var g = {}; - for (var resolverName in socket) { - var params = socket[resolverName]; - g[resolverName] = params; - } - return { size: 1, nspGroup: ( obj = {}, obj[publicNamespace] = g, obj ), publicNamespace: publicNamespace} -} + Object.defineProperties( EventService.prototype, prototypeAccessors ); + return EventService; +}(StoreService)); -/** - * @BUG we should check the socket part instead of expect the downstream to read the menu! - * We only need this when the enableAuth is true otherwise there is only one namespace - * @param {object} contract the socket part of the contract file - * @return {object} 1. remap the contract using the namespace --> resolvers - * 2. the size of the object (1 all private, 2 mixed public with private) - * 3. which namespace is public - */ -function groupByNamespace(contract) { - var socket = extractSocketPart(contract); - if (socket === false) { - throw new JsonqlError('groupByNamespace', SOCKET_NOT_FOUND_ERR) - } - var prop = {}; - prop[NSP_GROUP] = {}; - prop[PUBLIC_NAMESPACE] = null; - prop[SIZE] = 0; +// default - for (var resolverName in socket) { - var params = socket[resolverName]; - var namespace = params.namespace; - if (namespace) { - if (!prop[NSP_GROUP][namespace]) { - ++prop[SIZE]; - prop[NSP_GROUP][namespace] = {}; - } - prop[NSP_GROUP][namespace][resolverName] = params; - // get the public namespace - if (!prop[PUBLIC_NAMESPACE] && params[PUBLIC_KEY]) { - prop[PUBLIC_NAMESPACE] = namespace; - } +// this will generate a event emitter and will be use everywhere +// create a clone version so we know which one we actually is using +var JsonqlWsEvt = /*@__PURE__*/(function (EventEmitterClass) { + function JsonqlWsEvt(logger) { + if (typeof logger !== 'function') { + throw new Error("Just die here the logger is not a function!") } + logger("---> Create a new EventEmitter <---"); + // this ee will always come with the logger + // because we should take the ee from the configuration + EventEmitterClass.call(this, { logger: logger }); } - - return prop -} -/** - * @TODO this might change, what if we want to do room with ws - * 1. there will only be max two namespace - * 2. when it's normal we will have the stock path as namespace - * 3. when enableAuth then we will have two, one is jsonql/public + private - * @param {object} config options - * @return {array} of namespace(s) - */ -function getNamespace(config) { - var base = JSONQL_PATH; - if (config.enableAuth) { - // the public come first @1.0.1 we use the constants instead of the user supplied value - // @1.0.4 we use the config value again, because we could control this via the post init - return [ - [ base , config.privateNamespace ].join('/'), - [ base , config.publicNamespace ].join('/') - ] - } - return [ base ] -} + if ( EventEmitterClass ) JsonqlWsEvt.__proto__ = EventEmitterClass; + JsonqlWsEvt.prototype = Object.create( EventEmitterClass && EventEmitterClass.prototype ); + JsonqlWsEvt.prototype.constructor = JsonqlWsEvt; + + var prototypeAccessors = { name: { configurable: true } }; + + prototypeAccessors.name.get = function () { + return 'jsonql-ws-client-core' + }; + Object.defineProperties( JsonqlWsEvt.prototype, prototypeAccessors ); + + return JsonqlWsEvt; +}(EventService)); /** - * Got a problem with a contract that is public only the groupByNamespace is wrong - * which is actually not a problem when using a fallback, but to be sure things in order - * we could combine with the config to group it - * @param {object} config configuration - * @return {object} nspInfo object + * getting the event emitter + * @param {object} opts configuration + * @return {object} the event emitter instance */ -function getNspInfoByConfig(config) { - var contract = config.contract; - var enableAuth = config.enableAuth; - var namespaces = getNamespace(config); - var nspInfo = enableAuth ? groupByNamespace(contract) - : groupPublicNamespace(contract.socket, namespaces[0]); - // add the namespaces into it as well - return Object.assign(nspInfo, { namespaces: namespaces }) -} +var getEventEmitter = function (opts) { + var log = opts.log; + var eventEmitter = opts.eventEmitter; + + if (eventEmitter) { + log("eventEmitter is:", eventEmitter.name); + return eventEmitter + } + + return new JsonqlWsEvt( opts.log ) +}; // group all the small functions here @@ -6975,7 +7144,7 @@ var getHostName = function () { * @return {void} */ var clearMainEmitEvt = function (ee, namespace) { - var nsps = toArray$1(namespace); + var nsps = toArray(namespace); nsps.forEach(function (n) { ee.$off(createEvt(n, EMIT_REPLY_TYPE)); }); @@ -7067,8 +7236,6 @@ function createAuthMethods(obj, opts, ee) { // constants -var SOCKET_IO = JS_WS_SOCKET_IO_NAME; - var EMIT_EVT = EMIT_REPLY_TYPE; var UNKNOWN_RESULT = 'UKNNOWN RESULT!'; @@ -7085,10 +7252,10 @@ var MY_NAMESPACE = 'myNamespace'; * @return {void} nothing */ function respondHandler(data, resolver, rejecter) { - if (isObjectHasKey$1(data, ERROR_KEY)) { + if (isObjectHasKey(data, ERROR_KEY)) { // debugFn('-- rejecter called --', data[ERROR_KEY]) rejecter(data[ERROR_KEY]); - } else if (isObjectHasKey$1(data, DATA_KEY)) { + } else if (isObjectHasKey(data, DATA_KEY)) { // debugFn('-- resolver called --', data[DATA_KEY]) resolver(data[DATA_KEY]); } else { @@ -7116,7 +7283,7 @@ function actionCall(ee, namespace, resolverName, args, log) { log(("actionCall: " + outEventName + " --> " + resolverName), args); // This is the out going call - ee.$trigger(outEventName, [resolverName, toArray$1(args)]); + ee.$trigger(outEventName, [resolverName, toArray(args)]); // then we need to listen to the event callback here as well return new Promise(function (resolver, rejecter) { @@ -7355,7 +7522,11 @@ function generateResolvers(opts, ee, nspGroup) { var fn = createResolver(ee, namespace, resolverName, params, log); // this should set as a getter therefore can not be overwrite by accident // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee) - client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log)); + client = injectToFn( + client, + resolverName, + setupResolver(namespace, resolverName, params, fn, ee, log) + ); } } // resolve the clientto start the chain @@ -7372,21 +7543,22 @@ function generateResolvers(opts, ee, nspGroup) { * @param {object} nspGroup namespace keys * @return {array} [obj, opts, ee] */ -function createNamespaceErrorHandler(client, opts, ee, nspGroup) { +function createNamespaceErrorListener(client, opts, ee, nspGroup) { return [ - // using the onError as name - // @TODO we should follow the convention earlier - // make this a setter for the clientitself - objDefineProps(client, ON_ERROR_FN_NAME, function namespaceErrorCallbackHandler(namespaceErrorHandler) { - if (isFunc(namespaceErrorHandler)) { - // please note ON_ERROR_FN_NAME can add multiple listners - for (var namespace in nspGroup) { - // this one is very tricky, we need to make sure the trigger is calling - // with the namespace as well as the error - ee.$on(createEvt(namespace, ON_ERROR_FN_NAME), namespaceErrorHandler); + objDefineProps( + client, + ON_ERROR_FN_NAME, + function namespaceErrorCallbackHandler(namespaceErrorHandler) { + if (isFunc(namespaceErrorHandler)) { + // please note ON_ERROR_FN_NAME can add multiple listners + for (var namespace in nspGroup) { + // this one is very tricky, we need to make sure the trigger is calling + // with the namespace as well as the error + ee.$on(createEvt(namespace, ON_ERROR_FN_NAME), namespaceErrorHandler); + } } } - }), + ), opts, ee ] @@ -7399,14 +7571,18 @@ function createNamespaceErrorHandler(client, opts, ee, nspGroup) { * @param {object} ee Event Emitter * @return {array} [ obj, opts, ee ] */ -function createOnReadyHandler(client, opts, ee) { +function createOnReadyListener(client, opts, ee) { return [ - objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) { - if (isFunc(onReadyCallback)) { - // reduce it down to just one flat level - ee.$on(ON_READY_FN_NAME, onReadyCallback); + objDefineProps( + client, + ON_READY_FN_NAME, + function onReadyCallbackHandler(onReadyCallback) { + if (isFunc(onReadyCallback)) { + // reduce it down to just one flat level + ee.$on(ON_READY_FN_NAME, onReadyCallback); + } } - }), + ), opts, ee ] @@ -7454,6 +7630,7 @@ function setupFinalStep(obj, opts, ee) { } // resolvers generator + /** * prepare the methods * @param {object} opts configuration @@ -7462,25 +7639,22 @@ function setupFinalStep(obj, opts, ee) { * @return {object} of resolvers * @public */ -function generator(opts, nspMap, ee) { - - var args = [ +function callersGenerator(opts, nspMap, ee) { + var fns = [ generateResolvers, - createNamespaceErrorHandler, - createOnReadyHandler + createOnReadyListener, + createNamespaceErrorListener ]; if (opts.enableAuth) { - args.push( - createAuthMethods - ); + fns.push(createAuthMethods); } // we will always get back the [ obj, opts, ee ] // then we only return the obj (wsClient) - args.push(setupFinalStep); + fns.push(setupFinalStep); // run it - var fn = Reflect.apply(chainFns, null, args); + var generator = Reflect.apply(chainFns, null, fns); - return fn(opts, ee, nspMap[NSP_GROUP]) + return generator(opts, ee, nspMap[NSP_GROUP]) } var obj, obj$1, obj$2; @@ -7586,47 +7760,56 @@ function createRequiredParams(opts) { // the top level API - /** * 0.5.0 we break up the wsClientCore in two parts one without the config check - * @param {function} frameworkSocketEngine - * @param {object} config the already checked config - */ -function wsClientCoreAction(frameworkSocketEngine, config) { - return postCheckInjectOpts(config) - // the following two moved to wsPostConfig - .then(createRequiredParams) - .then( - function (ref) { - var opts = ref.opts; - var nspMap = ref.nspMap; - var ee = ref.ee; + * @param {function} socketClientListerner + * @return {function} to actually generate the client + */ +function wsClientCoreAction(socketClientListerner) { + /** + * This is a breaking change, to continue the onion skin design + * @param {object} config the already checked config + * @return {promise} resolve the client + */ + return function (config) { + if ( config === void 0 ) config = {}; - return frameworkSocketEngine(opts, nspMap, ee); - } - ) - .then( - function (ref) { - var opts = ref.opts; - var nspMap = ref.nspMap; - var ee = ref.ee; - return generator(opts, nspMap, ee); + return postCheckInjectOpts(config) + // the following two moved to wsPostConfig + .then(createRequiredParams) + .then( + function (ref) { + var opts = ref.opts; + var nspMap = ref.nspMap; + var ee = ref.ee; + + return socketClientListerner(opts, nspMap, ee); + } + ) + .then( // there is problem here, we wrap up the operation inside + function (ref) { + var opts = ref.opts; + var nspMap = ref.nspMap; + var ee = ref.ee; + + return callersGenerator(opts, nspMap, ee); + } + ) + .catch(function (err) { + console.error("jsonql-ws-core-client init error", err); + }) } - ) - .catch(function (err) { - console.error("jsonql-ws-core-client init error", err); - }) } /** * The main interface which will generate the socket clients and map all events - * @param {object} frameworkSocketEngine this is the one method export by various clients + * @param {object} socketClientListerner this is the one method export by various clients * @param {object} [configCheckMap={}] we should do all the checking in the core instead of the client * @param {object} [constProps={}] add this to supply the constProps from the downstream client * @return {function} accept a config then return the wsClient instance with all the available API */ -function wsClientCore(frameworkSocketEngine, configCheckMap, constProps) { +function wsClientCore(socketClientListerner, configCheckMap, constProps) { if ( configCheckMap === void 0 ) configCheckMap = {}; if ( constProps === void 0 ) constProps = {}; @@ -7635,7 +7818,7 @@ function wsClientCore(frameworkSocketEngine, configCheckMap, constProps) { if ( config === void 0 ) config = {}; return checkConfiguration(config, configCheckMap, constProps) - .then(function (opts) { return wsClientCoreAction(frameworkSocketEngine, opts); }); + .then(wsClientCoreAction(socketClientListerner)); } } @@ -7686,6 +7869,22 @@ function createNspAuthClient(namespace, opts) { // this use by client-event-handler +/** + * trigger errors on all the namespace onError handler + * @param {object} ee Event Emitter + * @param {array} namespaces nsps string + * @param {string} message optional + * @return {void} + */ +function triggerNamespacesOnError(ee, namespaces, message) { + namespaces.forEach( function (namespace) { + ee.$trigger( + createEvt(namespace, ON_ERROR_FN_NAME), + [{ message: message, namespace: namespace }] + ); + }); +} + /** * Handle the onerror callback * @param {object} ee event emitter @@ -7697,112 +7896,118 @@ var handleNamespaceOnError = function (ee, namespace, err) { ee.$trigger(createEvt(namespace, ON_ERROR_FN_NAME), [err]); }; -// This is share between different clients so we export it +// NOT IN USE AT THE MOMENT JUST KEEP IT HERE FOR THE TIME BEING + +/** + * Only when there is a private namespace then we bind to this event + * @param {object} nsps the available nsp(s) + * @param {array} namespaces available namespace + * @param {object} ee eventEmitter + * @param {object} opts configuration + * @return {void} + */ +var logoutEvtListener = function (nsps, namespaces, ee, opts) { + var log = opts.log; + // this will be available regardless enableAuth + // because the server can log the client out + ee.$on( + LOGOUT_EVENT_NAME, + function logoutEvtCallback() { + var privateNamespace = getPrivateNamespace(namespaces); + log((LOGOUT_EVENT_NAME + " event triggered")); + // disconnect(nsps, opts.serverType) + // we need to issue error to all the namespace onError Listerner + triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME); + // rebind all of the Listerner to the fake one + log(("logout from " + privateNamespace)); + + clearMainEmitEvt(ee, privateNamespace); + // we need to issue one more call to the server before we disconnect + // now this is a catch 22, here we are not suppose to do anything platform specific + // so that should fire before trigger this event + // clear out the nsp + nsps[privateNamespace] = null; + // add a NOT LOGIN error if call + notLoginWsListerner(privateNamespace, ee, opts); + } + ); +}; /** - * A Event handler placeholder when it's not connect to the private nsp + * 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 notLoginWsHandler = function (namespace, ee, opts) { +var notLoginListener = function (namespace, ee, opts) { var log = opts.log; + ee.$only( createEvt(namespace, EMIT_EVT), - function notLoginHandlerCallback(resolverName, args) { - log('[notLoginHandler] hijack the ws call', namespace, resolverName, args); + 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 handler, but wrap inside the error key + // also trigger the result Listerner, but wrap inside the error key ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error: error }]); } ); }; -/** - * get the private namespace - * @param {array} namespaces array - * @return {*} string on success - */ -var getPrivateNamespace = function (namespaces) { return ( - namespaces.length > 1 ? namespaces[0] : false -); }; +// This is share between different clients so we export it + /** * centralize all the comm in one place - * @param {object} opts configuration - * @param {object} nspMap this is not in the opts - * @param {object} ee Event Emitter instance * @param {function} bindSocketEventHandler binding the ee to ws --> this is the core bit * @param {object} nsps namespaced nsp * @return {void} nothing */ -function clientEventHandler$1(opts, nspMap, ee, bindSocketEventHandler, nsps) { - // since all these params already in the opts - var log = opts.log; - var namespaces = nspMap.namespaces; - // @1.1.3 add isPrivate prop to id which namespace is the private nsp - // then we can use this prop to determine if we need to fire the ON_LOGIN_PROP_NAME event - var privateNamespace = getPrivateNamespace(namespaces); - var isPrivate = false; - var hasPrivate = false; - // loop - // @BUG for io this has to be in order the one with auth need to get call first - // The order of login is very import we need to run in order here to make sure - // one is execute then the other - namespaces.forEach(function (namespace) { - isPrivate = privateNamespace === namespace; - if (!hasPrivate) { - hasPrivate = isPrivate; - } - // log(namespace, ' --> nsps --> ', nsps[namespace]) - if (nsps[namespace]) { - - log('[call bindWsHandler]', isPrivate, namespace); - var args = [namespace, nsps[namespace], ee, isPrivate, opts]; - // @TODO need to double check this - if (opts.serverType === SOCKET_IO) { - var nspGroup = nspMap.nspGroup; - args.push(nspGroup[namespace]); +function clientEventListener(bindSocketEventListener, nsps) { + /** + * BREAKING CHANGE instead of one flat structure + * we return a function to accept the two + * @param {object} opts configuration + * @param {object} nspMap this is not in the opts + * @param {object} ee Event Emitter instance + * @return {array} although we return something but this is the last step and nothing to do further + */ + return function (opts, nspMap, ee) { + // since all these params already in the opts + var log = opts.log; + var namespaces = nspMap.namespaces; + // @1.1.3 add isPrivate prop to id which namespace is the private nsp + // then we can use this prop to determine if we need to fire the ON_LOGIN_PROP_NAME event + var privateNamespace = getPrivateNamespace$1(namespaces); + + return namespaces.map(function (namespace) { + var isPrivate = privateNamespace === namespace; + log(namespace, (" --> " + (isPrivate ? 'private': 'public') + " nsp --> "), nsps[namespace] !== false); + if (nsps[namespace]) { + log('[call bindWsHandler]', isPrivate, namespace); + + 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 + // @TODO but it should be a not connect handler + // when it's not login (or fail) this should be handle differently + notLoginListener(namespace, ee, opts); } - Reflect.apply(bindSocketEventHandler, null, args); - } else { - log(("binding notLoginWsHandler to " + namespace)); - // a dummy placeholder - // @TODO but it should be a not connect handler - // when it's not login (or fail) this should be handle differently - notLoginWsHandler(namespace, ee, opts); - } - }); - // logout event handler - if (hasPrivate) { - log("Has private and add logoutEvtHandler"); - // logoutEvtHandler(nsps, namespaces, ee, opts) + if (isPrivate) { + log("Has private and add logoutEvtHandler"); + logoutEvtListener(nsps, namespaces, ee, opts); + } + // just return something its not going to get use anywhere + return isPrivate + }) } - // finally the disconnect event handlers - // disconnectHandler(nsps, namespaces, ee, opts) -} - -// this will be part of the init client sequence - - -/** - * Create a generic intercom method - * @param {string} type the event type - * @param {array} args if any - * @return {string} formatted payload to send - */ -function createIntercomPayload(type) { - var args = [], len = arguments.length - 1; - while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; - - var ts = timestamp(); - var payload = [type].concat(args); - payload.push(ts); - return createQueryStr(INTERCOM_RESOLVER_NAME, payload) } /* base.js */ @@ -7812,9 +8017,9 @@ var TIMESTAMP_PARAM_NAME$1 = 'TS'; var LOGIN_EVENT_NAME$1 = '__login__'; var LOGOUT_EVENT_NAME$1 = '__logout__'; // for ws servers -var WS_REPLY_TYPE = '__reply__'; -var WS_EVT_NAME = '__event__'; -var WS_DATA_NAME = '__data__'; +var WS_REPLY_TYPE$1 = '__reply__'; +var WS_EVT_NAME$1 = '__event__'; +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'; @@ -7841,6 +8046,61 @@ var wsClientConstProps = { // pass the different type of ws to generate the client +/** + * Group the ping and get respond create new client in one + * @param {object} ws + * @param {object} WebSocket + * @param {string} url + * @param {function} resolver + * @param {function} rejecter + * @param {boolean} auth client or not + * @return {promise} resolve the confirm client + */ +function initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) { + // @TODO how to we id this client can issue a CSRF + // by origin? + ws.onopen = function onOpenCallback() { + ws.send(createInitPing()); + }; + + ws.onmessage = function onMessageCallback(payload) { + try { + var header = extractPingResult(payload.data); + // @NOTE the break down test in ws-client-core show no problems + // the problem was cause by malform nspInfo that time? + setTimeout(function () { // delay or not show no different but just on the safe side + ws.terminate(); + }, 50); + var newWs = new WebSocket(url, Object.assign(wsOptions, header)); + resolver(newWs); + } catch(e) { + rejecter(e); + } + }; + + ws.onerror = function onErrorCallback(err) { + rejecter(err); + }; +} + +/** + * less duplicated code the better + * @param {object} WebSocket + * @param {string} url formatted url + * @param {object} options or not + * @return {promise} resolve the actual verified client + */ +function asyncConnect(WebSocket, url, options) { + + return new Promise(function (resolver, rejecter) { + + var unconfirmClient = new WebSocket(url, options); + + initPingAction(unconfirmClient, WebSocket, url, resolver, rejecter, options); + }) +} + + /** * The bug was in the wsOptions where ws don't need it but socket.io do * therefore the object was pass as second parameter! @@ -7861,17 +8121,9 @@ function initWebSocketClient(WebSocket, auth, log) { if ( wsOptions === void 0 ) wsOptions = {}; var _url = fixWss(url); - log(("nspClient: \n" + _url + "\n"), wsOptions); - return new Promise(function (resolver, rejecter) { - - var unconfirmClient = new WebSocket(_url, wsOptions); - - resolver(unconfirmClient); - - // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) - }) + return asyncConnect(WebSocket, _url, wsOptions) } } @@ -7888,16 +8140,9 @@ function initWebSocketClient(WebSocket, auth, log) { var ws_url = fixWss(url); // console.log('what happen here?', url, ws_url, token) var _url = token && typeof token === 'string' ? (ws_url + "?" + TOKEN_PARAM_NAME + "=" + token) : ws_url; - log(("nspAuthClient: \n" + _url + "\n"), wsOptions); - return new Promise(function (resolver, rejecter) { - var unconfirmClient = new WebSocket(_url, wsOptions); - - resolver(unconfirmClient); - - // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions) - }) + return asyncConnect(WebSocket, _url, wsOptions) } } @@ -10119,7 +10364,7 @@ var inArray$2 = function (arr, value) { return !!arr.filter(function (a) { retur * @param {boolean} [t=true] or throw * @return {*} json object on success */ -var parseJson = function(n, t) { +var parseJson$1 = function(n, t) { if ( t === void 0 ) t=true; try { @@ -10164,11 +10409,11 @@ var createEvt$1 = function () { * @param {*} n input * @return {object} correct JSON object */ -var toJson = function (n) { +var toJson$1 = function (n) { if (typeof n === 'string') { - return parseJson(n) + return parseJson$1(n) } - return parseJson(JSON.stringify(n)) + return parseJson$1(JSON.stringify(n)) }; // generic placeholder function @@ -10348,23 +10593,23 @@ function createQueryStr$1(resolverName, args, jsonp) { // There are the socket related methods ported back from -var PAYLOAD_NOT_DECODED_ERR = 'payload can not decoded'; -var WS_KEYS = [ - WS_REPLY_TYPE, - WS_EVT_NAME, - WS_DATA_NAME +var PAYLOAD_NOT_DECODED_ERR$1 = 'payload can not decoded'; +var WS_KEYS$1 = [ + WS_REPLY_TYPE$1, + WS_EVT_NAME$1, + WS_DATA_NAME$1 ]; /** * @param {string|object} payload should be string when reply but could be transformed * @return {boolean} true is OK */ -var isWsReply = function (payload) { - var json = isString$3(payload) ? toJson(payload) : payload; +var isWsReply$1 = function (payload) { + var json = isString$3(payload) ? toJson$1(payload) : payload; var data = json.data; if (data) { - var result = WS_KEYS.filter(function (key) { return isObjectHasKey$2(data, key); }); - return (result.length === WS_KEYS.length) ? data : false + var result = WS_KEYS$1.filter(function (key) { return isObjectHasKey$2(data, key); }); + return (result.length === WS_KEYS$1.length) ? data : false } return false }; @@ -10374,24 +10619,24 @@ var isWsReply = function (payload) { * @param {function} [cb=nil] this is for extracting the TS field or when it's error * @return {object} false on failed */ -var extractWsPayload = function (payload, cb) { +var extractWsPayload$1 = function (payload, cb) { if ( cb === void 0 ) cb = nil$1; try { - var json = toJson(payload); + var json = toJson$1(payload); // now handle the data var _data; - if ((_data = isWsReply(json)) !== false) { + if ((_data = isWsReply$1(json)) !== false) { // note the ts property is on its own cb(TIMESTAMP_PARAM_NAME$1, json[TIMESTAMP_PARAM_NAME$1]); return { - data: toJson(_data[WS_DATA_NAME]), - resolverName: _data[WS_EVT_NAME], - type: _data[WS_REPLY_TYPE] + data: toJson$1(_data[WS_DATA_NAME$1]), + resolverName: _data[WS_EVT_NAME$1], + type: _data[WS_REPLY_TYPE$1] } } - throw new JsonqlError$2(PAYLOAD_NOT_DECODED_ERR, payload) + throw new JsonqlError$2(PAYLOAD_NOT_DECODED_ERR$1, payload) } catch(e) { return cb(ERROR_KEY$1, e) } @@ -10491,7 +10736,7 @@ function bindSocketEventHandler(namespace, ws, ee, isPrivate, opts) { // log(`ws.onmessage raw payload`, payload) // @TODO the payload actually contain quite a few things - is that changed? // type: message, data: data_send_from_server - var json = extractWsPayload(payload.data); + var json = extractWsPayload$1(payload.data); var resolverName = json.resolverName; var type = json.type; @@ -10556,16 +10801,16 @@ function bindSocketEventHandler(namespace, ws, ee, isPrivate, opts) { * @return {object} what comes in what goes out */ function createNsp(opts, nspMap, ee) { - // arguments for clientEventHandler - var args = [opts, nspMap, ee, bindSocketEventHandler]; // now create the nsps // const { namespaces } = nspMap var token = opts.token; return createNspAction$1(opts, nspMap, token) .then(function (nsps) { - args.push(nsps); - Reflect.apply(clientEventHandler$1, null, args); + var listenerFn = clientEventListener(bindSocketEventHandler, nsps); + // now run it + listenerFn(opts, nspMap, ee); + if (opts.enableAuth) { loginEventHandler(opts, nspMap, ee); } diff --git a/packages/@jsonql/ws/main.js.map b/packages/@jsonql/ws/main.js.map index dc94d863..4534c941 100644 --- a/packages/@jsonql/ws/main.js.map +++ b/packages/@jsonql/ws/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","sources":["node_modules/rollup-plugin-node-globals/src/global.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arrayMap.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_objectToString.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isObjectLike.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseSlice.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseFindIndex.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseIsNaN.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_strictIndexOf.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_asciiToArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_hasUnicode.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_unicodeToArray.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/number.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/string.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/boolean.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/any.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/constants.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/combine.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/array.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_overArg.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/validation-error.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/validator.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_listCacheClear.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/eq.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_stackDelete.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_stackGet.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_stackHas.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isObject.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_toSource.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_getValue.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_hashDelete.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_isKeyable.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_createBaseFor.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_copyArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_isPrototype.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/isLength.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/stubFalse.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseUnary.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_safeGet.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseTimes.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_isIndex.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_nativeKeysIn.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/identity.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_apply.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/constant.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_shortOut.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_setCacheAdd.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_setCacheHas.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arraySome.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_cacheHas.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_mapToArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_setToArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arrayPush.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_arrayFilter.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/stubArray.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_matchesStrictComparable.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseHasIn.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseProperty.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/negate.js","../../ws-client-core/node_modules/_lodash-es@4.17.15@lodash-es/_baseFindKey.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/is-in-array.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/enum-error.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/type-error.js","../../ws-client-core/node_modules/_jsonql-errors@1.2.1@jsonql-errors/src/checker-error.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/run-validation.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/check-options-async.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/construct-config.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/src/options/index.js","../../ws-client-core/node_modules/_jsonql-params-validator@1.6.1@jsonql-params-validator/index.js","../../ws-client-core/src/utils/get-log-fn.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/constants.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/store.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/utils.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/suspend.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/store-service.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/src/event-service.js","../../ws-client-core/node_modules/_@to1source_event@1.0.0@@to1source/event/index.js","../../ws-client-core/src/utils/get-event-emitter.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/generic.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/contract.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/timestamp.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/params-api.js","../../ws-client-core/node_modules/_jsonql-utils@1.2.1@jsonql-utils/src/namespace.js","../../ws-client-core/src/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-send-method.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/setup-intercom.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","../../ws-client-core/src/share/create-nsp-clients.js","../../ws-client-core/src/share/trigger-namespaces-on-error.js","../../ws-client-core/src/share/client-event-handler.js","../../ws-client-core/src/share/intercom-methods.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.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/login-event-handler.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/create-nsp/bind-socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.js","src/node-ws-client.js"],"sourcesContent":["export default (typeof global !== \"undefined\" ? global :\n typeof self !== \"undefined\" ? self :\n typeof window !== \"undefined\" ? window : {});\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","/**\n * 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","// 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","/**\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","// 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","// 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","// 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","/**\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","/** 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","// 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","// 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","// 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// generic placeholder function\nexport const nil = () => false\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/**\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","// 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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(client, resolverName, setupResolver(namespace, resolverName, params, fn, ee, log))\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/**\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 createNamespaceErrorHandler(client, opts, ee, nspGroup) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the clientitself\n objDefineProps(client, ON_ERROR_FN_NAME, 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 opts,\n ee\n ]\n}\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 createOnReadyHandler(client, opts, ee) {\n return [\n objDefineProps(client, ON_READY_FN_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n} from './resolver-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 generator(opts, nspMap, ee) {\n\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyHandler\n ]\n if (opts.enableAuth) {\n args.push(\n createAuthMethods\n )\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n args.push(setupFinalStep)\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n\n return fn(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 { generator } from './core'\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} frameworkSocketEngine \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(frameworkSocketEngine, config) {\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => frameworkSocketEngine(opts, nspMap, ee)\n )\n .then(\n ({opts, nspMap, ee}) => generator(opts, nspMap, ee)\n )\n .catch(err => {\n console.error(`jsonql-ws-core-client init error`, err)\n })\n}\n\n/**\n * The main interface which will generate the socket clients and map all events\n * @param {object} frameworkSocketEngine 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(frameworkSocketEngine, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(opts => wsClientCoreAction(frameworkSocketEngine, opts))\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}","// 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\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, SOCKET_IO, DISCONNECTED_ERROR_MSG } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A Event handler 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 */\nconst notLoginWsHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n log('[notLoginHandler] 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 handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, ON_RESULT_FN_NAME), [{ error }])\n }\n )\n}\n\n/**\n * get the private namespace\n * @param {array} namespaces array\n * @return {*} string on success\n */\nconst getPrivateNamespace = (namespaces) => (\n namespaces.length > 1 ? namespaces[0] : false\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 */\nconst logoutEvtHandler = (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(LOGOUT_EVENT_NAME, function logoutEvtHandlerAction() {\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 handler\n triggerNamespacesOnError(ee, [privateNamespace], LOGOUT_EVENT_NAME)\n // rebind all of the handler 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 notLoginWsHandler(privateNamespace, ee, opts)\n })\n}\n\n/**\n * A Event handler 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 */\nconst disconnectedHandler = (namespace, ee, opts) => {\n const { log } = opts \n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function disconnectedHandlerCallback(resolverName, args) {\n log(`[disconnectedHandler] 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 handler, 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 handler, 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 */\nconst disconnectHandler = (nsps, namespaces, ee, opts) => {\n const { log } = opts \n ee.$on(DISCONNECT_EVENT_NAME, function disconnectEvtHandler() {\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 disconnectedHandler(namespace, ee, opts)\n })\n })\n}\n\n/**\n * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {object} nspMap this is not in the opts \n * @param {object} ee Event Emitter instance\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 clientEventHandler(opts, nspMap, ee, bindSocketEventHandler, nsps) {\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 let isPrivate = false\n let hasPrivate = false\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run in order here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace\n if (!hasPrivate) {\n hasPrivate = isPrivate\n }\n // log(namespace, ' --> nsps --> ', nsps[namespace])\n if (nsps[namespace]) {\n\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n // @TODO need to double check this\n if (opts.serverType === SOCKET_IO) {\n let { nspGroup } = nspMap\n args.push(nspGroup[namespace])\n }\n Reflect.apply(bindSocketEventHandler, null, args)\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 notLoginWsHandler(namespace, ee, opts)\n }\n })\n // logout event handler \n if (hasPrivate) {\n log(`Has private and add logoutEvtHandler`)\n // logoutEvtHandler(nsps, namespaces, ee, opts)\n }\n // finally the disconnect event handlers\n // disconnectHandler(nsps, namespaces, ee, opts) \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 * 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 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 json = toJson(payload)\n const result = extractWsPayload(json)\n if (result[DATA_KEY] && result[DATA_KEY][CSRF_HEADER_KEY]) {\n return {\n [HEADERS_KEY]: result[DATA_KEY]\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 createInitPing, \n extractPingResult, \n createIntercomPayload \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 // the csrf cause all kinds of problem so we abandoned it for now\n return resolver(ws)\n /*\n // terminate the client \n ws.terminate()\n // return the new one with csrf header\n // @BUG too quick and kill the socket?\n setTimeout(() => {\n const newWs = new WebSocket(url, Object.assign(wsOptions, header)) \n resolver(newWs) \n }, 50)\n */\n } catch(e) {\n rejecter(e)\n }\n }\n\n ws.onerror = function onErrorCallback(err) {\n rejecter(err)\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 \n log(`nspClient: \\n${_url}\\n`, wsOptions)\n\n return new Promise((resolver, rejecter) => { \n \n const unconfirmClient = new WebSocket(_url, wsOptions)\n \n resolver(unconfirmClient)\n\n // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\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\n log(`nspAuthClient: \\n${_url}\\n`, wsOptions)\n\n return new Promise((resolver, rejecter) => {\n const unconfirmClient = new WebSocket(_url, wsOptions)\n \n resolver(unconfirmClient)\n\n // initPingAction(unconfirmClient, WebSocket, _url, resolver, rejecter, wsOptions)\n })\n }\n}\n\nexport { initWebSocketClient }","/** 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","// @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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError,\n createIntercomPayload\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nconst logoutEventListener = (ee, ws) => {\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_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}\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\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventListener(ee, ws)\n }\n\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventHandler } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // arguments for clientEventHandler\n const args = [opts, nspMap, ee, bindSocketEventHandler]\n // now create the nsps\n // const { namespaces } = nspMap\n const { token } = opts\n\n return createNspAction(opts, nspMap, token)\n .then(nsps => {\n args.push(nsps)\n Reflect.apply(clientEventHandler, null, args)\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n }) \n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\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 * @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 opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log) \n // @1.0.7 remove later once everything fixed \n \n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ 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/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/callers/setup-auth-methods.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/setup-intercom.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/client-event-listener.js","src/options/index.js","src/core/create-websocket-binding/init-websocket-client.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/login-event-handler.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/create-nsp/bind-socket-event-handler.js","src/core/create-nsp/create-nsp.js","src/core/create-nsp/index.js","src/core/create-websocket-binding/bind-framework-to-jsonql.js","src/node/node-framework-socket-engine.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","// 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 * @TODO this is now become unnecessary because the login is a slave to the\n * http-client - but keep this for now and see what we want to do with it later\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 createOnLoginhandler = (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 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 createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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 resolver(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 // 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(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'\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 * 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 respondHandler(args, messageCallback, (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 */\nexport function setupResolver(namespace, resolverName, params, fn, ee, log) {\n let fns = [\n setupNamespace, \n setupOnResult, \n setupOnMessage, \n setupOnError, \n setupSendMethod\n ]\n \n // get the executor\n const executor = Reflect.apply(chainFns, null, fns)\n const args = [fn, ee, namespace, resolverName, params, log]\n\n return Reflect.apply(executor, null, args)\n}\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\nimport { finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport { setupResolver } from './setup-resolver'\nimport { actionCall } from './action-call'\nimport { \n createEvt, \n objDefineProps, \n isFunc, \n injectToFn \n} from '../utils'\nimport {\n ON_ERROR_FN_NAME,\n ON_READY_FN_NAME\n} from 'jsonql-constants'\n\n/**\n * create the actual function to send message to server\n * @param {object} ee EventEmitter instance\n * @param {string} namespace this resolver end point\n * @param {string} resolverName name of resolver as event name\n * @param {object} params from contract\n * @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 * 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 let client= {}\n let { log } = opts\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 // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n client = injectToFn(\n client, \n resolverName, \n setupResolver(namespace, resolverName, params, fn, ee, log)\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/**\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 createNamespaceErrorListener(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/**\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 createOnReadyListener(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 ee.$on(ON_READY_FN_NAME, onReadyCallback)\n }\n }\n ),\n opts,\n ee\n ]\n}\n\n\n\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 } from '../utils'\nimport { DISCONNECT_EVENT_NAME } from 'jsonql-constants'\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 { disconnectHandlerName } = opts\n return injectToFn(client, disconnectHandlerName, function disconnectHandler(...args) {\n ee.$trigger(DISCONNECT_EVENT_NAME, args)\n })\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 { chainFns } from '../utils'\nimport { createAuthMethods } from './setup-auth-methods'\nimport {\n generateResolvers,\n createOnReadyListener,\n createNamespaceErrorListener\n} from './generator-methods'\nimport {\n setupFinalStep \n} from './setup-final-step'\nimport {\n NSP_GROUP\n} from 'jsonql-constants'\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 createOnReadyListener,\n createNamespaceErrorListener\n ]\n if (opts.enableAuth) {\n fns.push(createAuthMethods)\n } \n // we will always get back the [ obj, opts, ee ]\n // then we only return the obj (wsClient)\n fns.push(setupFinalStep)\n // run it\n const generator = Reflect.apply(chainFns, null, fns)\n\n return generator(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 * @param {object} opts checked --> merge --> injected \n * @return {object} {opts, nspMap, ee} \n */\nfunction createRequiredParams(opts) {\n return {\n opts,\n nspMap: getNspInfoByConfig(opts),\n ee: opts.eventEmitter \n }\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 * 0.5.0 we break up the wsClientCore in two parts one without the config check \n * @param {function} socketClientListerner \n * @return {function} to actually generate the client\n */\nexport function wsClientCoreAction(socketClientListerner) {\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 (config = {}) => {\n\n return postCheckInjectOpts(config)\n // the following two moved to wsPostConfig\n .then(createRequiredParams)\n .then(\n ({opts, nspMap, ee}) => socketClientListerner(opts, nspMap, ee)\n )\n .then( // there is problem here, we wrap up the operation inside\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(socketClientListerner, configCheckMap = {}, constProps = {}) {\n // we need to inject property to this client later\n return (config = {}) => checkConfiguration(config, configCheckMap, constProps)\n .then(wsClientCoreAction(socketClientListerner))\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/**\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 clientEventListener(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\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 \n const unconfirmClient = new WebSocket(url, options)\n \n 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 }","/** 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","// @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 { LOGIN_EVENT_NAME } from 'jsonql-constants'\nimport { clearMainEmitEvt } from '../modules'\n\n/**\n * create a login event handler \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 loginEventHandler(opts, nspMap, ee) {\n const { log } = opts\n const { namespaces } = nspMap\n\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandlerCallback(tokenFromLoginAction) {\n \n log('createClient LOGIN_EVENT_NAME $only handler')\n\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNspAction(opts, nspMap, tokenFromLoginAction)\n // rebind it\n Reflect.apply(\n clientEventHandler, // @NOTE is this the problem that cause the hang up?\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\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// generic placeholder function\nexport const nil = () => false\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","/**\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/**\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","// the WebSocket main handler\nimport {\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_KEY,\n\n ON_ERROR_FN_NAME,\n ON_MESSAGE_FN_NAME,\n ON_RESULT_FN_NAME,\n ON_READY_FN_NAME,\n ON_LOGIN_FN_NAME\n} from 'jsonql-constants'\nimport { \n createQueryStr, \n createEvt, \n extractWsPayload \n} from 'jsonql-utils/module'\nimport {\n handleNamespaceOnError,\n createIntercomPayload\n} from '../modules'\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 */\nconst 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 * Handle the logout event when it's enableAuth\n * @param {object} ee eventEmitter\n * @param {object} ws the WebSocket instance\n * @return {void}\n */\nconst logoutEventListener = (ee, ws) => {\n // listen to the LOGOUT_EVENT_NAME when this is a private nsp\n ee.$on(LOGOUT_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}\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\n log(`log test, isPrivate:`, isPrivate)\n // connection open\n ws.onopen = function onOpenCallback() {\n \n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(ON_READY_FN_NAME, namespace)\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 \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 // 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.$trigger(e1, [json])\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.$trigger(e2, [json])\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 console.error(`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 if (isPrivate) {\n logoutEventListener(ee, ws)\n }\n\n}\n","// actually binding the event client to the socket client\n\n// from the jsonql-ws-client-core\nimport { clientEventListener } from '../modules'\n// local \nimport { createNspAction } from './create-nsp-action'\nimport { loginEventHandler } from './login-event-handler'\nimport { bindSocketEventHandler } from './bind-socket-event-handler'\n\n/**\n * create the NSP(s) and determine if this require auth or not \n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nfunction createNsp(opts, nspMap, ee) {\n // now create the nsps\n // const { namespaces } = nspMap\n const { token } = opts\n\n return createNspAction(opts, nspMap, token)\n .then(nsps => {\n const listenerFn = clientEventListener(bindSocketEventHandler, nsps)\n // now run it\n listenerFn(opts, nspMap, ee)\n\n if (opts.enableAuth) {\n loginEventHandler(opts, nspMap, ee)\n }\n // return what input\n return { opts, nspMap, ee }\n }) \n}\n\nexport { createNsp }","// breaking up the create-nsp.js file \n// then regroup them back together here \nimport { createNsp } from './create-nsp'\n\nexport default createNsp\n","// share method to create the wsClientResolver\nimport { initWebSocketClient } from './init-websocket-client'\nimport createNsp from '../create-nsp'\nimport { NSP_CLIENT, NSP_AUTH_CLIENT } from 'jsonql-constants'\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 * @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 opts[NSP_CLIENT] = initWebSocketClient(frameworkModule, false, log)\n opts[NSP_AUTH_CLIENT] = initWebSocketClient(frameworkModule, true, log) \n // @1.0.7 remove later once everything fixed \n \n log(`bindFrameworkToJsonql`, ee.name, nspMap)\n // console.log(`contract`, opts.contract)\n return createNsp(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 nodeFrameworkSocketEngine from './node/node-framework-socket-engine'\n\n// export back the function and that's it\nexport default function wsNodeClient(config = {}, constProps = {}) {\n const initClientMethod = wsClientCore(\n nodeFrameworkSocketEngine, \n {}, \n Object.assign({}, wsClientConstProps, constProps)\n )\n return initClientMethod(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;;;;;;;;;;;;;;;;;"} \ 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 355c7b34..1d48a8d7 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 @@ -46,11 +46,12 @@ function initPingAction(ws, WebSocket, url, resolver, rejecter, wsOptions) { /** * less duplicated code the better + * @param {object} WebSocket * @param {string} url formatted url * @param {object} options or not * @return {promise} resolve the actual verified client */ -function asyncConnect(url, options) { +function asyncConnect(WebSocket, url, options) { return new Promise((resolver, rejecter) => { @@ -81,7 +82,7 @@ function initWebSocketClient(WebSocket, auth, log) { const _url = fixWss(url) log(`nspClient: \n${_url}\n`, wsOptions) - return asyncConnect(_url, wsOptions) + return asyncConnect(WebSocket, _url, wsOptions) } } @@ -98,7 +99,7 @@ function initWebSocketClient(WebSocket, auth, log) { const _url = token && typeof token === 'string' ? `${ws_url}?${TOKEN_PARAM_NAME}=${token}` : ws_url log(`nspAuthClient: \n${_url}\n`, wsOptions) - return asyncConnect(_url, wsOptions) + return asyncConnect(WebSocket, _url, wsOptions) } } -- Gitee From c754d8cbea9a7d6c9ab73ab4ed5e023ed2eb0887 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 15:32:45 +0800 Subject: [PATCH 52/66] need to fix the missing helloWorld part in the public contract first --- packages/ws-client-core/src/callers/setup-final-step.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 943e1611..d7c25047 100644 --- a/packages/ws-client-core/src/callers/setup-final-step.js +++ b/packages/ws-client-core/src/callers/setup-final-step.js @@ -1,7 +1,6 @@ - - +// The final step of the setup before it returns the client import { setupInterCom } from './setup-intercom' - +// import { HELLO_FN } from 'jsonql-constants' /** * The final step to return the client @@ -20,6 +19,9 @@ function setupFinalStep(obj, opts, ee) { // create the ws client first then the host client client.eventEmitter = opts.eventEmitter client.log = opts.log + // we just inject a helloWorld method here + // client[HELLO_FN] = + return client } -- Gitee From 56747bf6bb8eaa71f7b13193935fae1e329a9e80 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 16:00:56 +0800 Subject: [PATCH 53/66] Run basic test to check if it crash --- packages/contract-cli/package.json | 2 +- .../contract-cli/src/public-contract/index.js | 33 +++++++++++++++++-- packages/contract-cli/tests/koa-debug.test.js | 9 +++-- packages/contract-cli/tests/socket.test.js | 4 +-- 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/packages/contract-cli/package.json b/packages/contract-cli/package.json index 45b541d9..577ed712 100755 --- a/packages/contract-cli/package.json +++ b/packages/contract-cli/package.json @@ -17,7 +17,7 @@ "cli": "DEBUG=jsonql-contract* node ./cli.js", "cli:watch": "DEBUG=jsonql-contract* node ./watch.js", "test": "ava", - "test:debug": "DEBUG=jsonql* ava tests/koa-debug.donttest.js", + "test:debug": "DEBUG=jsonql* ava tests/koa-debug.test.js", "test:socket": "DEBUG=jsonql-contract* ava ./tests/socket.test.js", "test:cli": "npm run cli configFile ./tests/fixtures/cmd-config-test.js", "test:doc": "DEBUG=jsonql-contract:* ava ./tests/contract-with-doc.test.js", diff --git a/packages/contract-cli/src/public-contract/index.js b/packages/contract-cli/src/public-contract/index.js index d2b76126..03b6060f 100644 --- a/packages/contract-cli/src/public-contract/index.js +++ b/packages/contract-cli/src/public-contract/index.js @@ -3,6 +3,10 @@ const { join } = require('path') const fsx = require('fs-extra') const { merge } = require('lodash') const { JsonqlError } = require('jsonql-errors') +const { + SOCKET_NAME, + QUERY_NAME +} = require('jsonql-constants') const { getDebug } = require('../utils') const debug = getDebug('public-contract') @@ -51,6 +55,7 @@ const cleanForPublic = (json, config) => { } /** + * @TODO * using the NODE_ENV to check if there is extra contract file * @param {string} contractDir directory store contract * @return {object} empty object when nothing @@ -65,6 +70,28 @@ function getEnvContractFile(contractDir) { return {} } +/** + * When this contract contain a socket field + * then we can use this to inject extra into it + * @param {object} contractJson the partially generated contract file + * @param {object} helloContract the helloWorld contract + * @return {object} the contract with socket part added helloWorld (or more later) + */ +function processSocketContract(contractJson, helloContract) { + if (contractJson[SOCKET_NAME]) { + debug('processSocketContract', contractJson[SOCKET_NAME]) + + const helloWorldPart = helloContract[QUERY_NAME] + return merge(contractJson, { + [SOCKET_NAME]: helloWorldPart + }) + } + + return contractJson +} + + + /** * add an expired timstamp to the public contract * @param {object} config configuration @@ -91,7 +118,7 @@ function publicContractGenerator(config, contractJson) { if (!contractDir) { throw new JsonqlError('Contract directory is undefined!') } - const baseContract = fsx.readJsonSync(join(__dirname, 'hello-world.json')) + const helloContract = fsx.readJsonSync(join(__dirname, 'hello-world.json')) // env contract file - this should not get written to file // @TODO disable this feature for now and decide if we need it later const extraContracts = {} @@ -101,8 +128,8 @@ function publicContractGenerator(config, contractJson) { return cleanForPublic( merge( {}, - baseContract, - contractJson, + helloContract, + processSocketContract(contractJson, helloContract), extraContracts, expiredEntry ), diff --git a/packages/contract-cli/tests/koa-debug.test.js b/packages/contract-cli/tests/koa-debug.test.js index e0345b84..4bff5873 100644 --- a/packages/contract-cli/tests/koa-debug.test.js +++ b/packages/contract-cli/tests/koa-debug.test.js @@ -24,10 +24,10 @@ test(`First test the contract api directly`, async t => { debug(inspect(result, false, null)) - t.truthy(result.mutation && result.mutation.updateMsService) + t.truthy(result.query && result.mutation, 'It should have the two basic required fields') }) -test.only(`It should able to generate a contract without error`, async t => { +test(`It should able to generate a contract without error`, async t => { const result = await contractGenerator({ resolverDir, contractDir, @@ -36,5 +36,8 @@ test.only(`It should able to generate a contract without error`, async t => { debug(inspect(result, false, null)) - t.truthy(result.mutation && result.mutation.updateMsService) + t.truthy(result.mutation && result.mutation.updateMsService, 'It should have mutation field and associate method property') + + t.falsy(result.socket, 'It should not have a socket field') + }) diff --git a/packages/contract-cli/tests/socket.test.js b/packages/contract-cli/tests/socket.test.js index 2e083ad7..67539a8b 100644 --- a/packages/contract-cli/tests/socket.test.js +++ b/packages/contract-cli/tests/socket.test.js @@ -24,7 +24,7 @@ test.cb(`It should able to return a list of socket auth files`, t => { getSocketAuthResolverFiles(resolverDir) .then(files => { - + debug('files', files) t.truthy(files.length) @@ -50,4 +50,4 @@ test.cb(`It should able to generate partial contract for socket auth`, t => { }) -test.todo(`It should able to generate new entry when socket/auth has content`) +test.todo(`It should able to generate new entry when socket / auth has content`) -- Gitee From c7bea175f60e0479db7295e8ac0a2df5c385a7a0 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 16:07:22 +0800 Subject: [PATCH 54/66] test passed and verify working --- packages/contract-cli/tests/generator.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/contract-cli/tests/generator.test.js b/packages/contract-cli/tests/generator.test.js index 3b9a0b73..322fb17b 100755 --- a/packages/contract-cli/tests/generator.test.js +++ b/packages/contract-cli/tests/generator.test.js @@ -85,6 +85,8 @@ test.only('Should able to create a public-contract.json', async t => { t.true(json.socket.alwaysAvailable.namespace.indexOf('public') > -1) // check if there is a description field in each + t.truthy(json.socket.helloWorld, 'It should have a helloWorld method injected to it') + t.falsy(json.query.anyoneCanGetThis.description, 'should not have a description in the public query') // @1.7.6 the description field is kept in the file // t.falsy(json.query.privateFn.description, 'should not have a description in the private query') -- Gitee From 2c365222b4654c2c63c60e683bf4cec7e144c5b3 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 19:58:09 +0800 Subject: [PATCH 55/66] clean up some old interface --- packages/contract-cli/package.json | 12 ++++++------ .../src/generator/generate-output.js | 8 +++----- packages/contract-cli/src/generator/index.js | 4 +--- packages/contract-cli/src/utils.js | 16 ++++++++-------- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/packages/contract-cli/package.json b/packages/contract-cli/package.json index 577ed712..949e94f0 100755 --- a/packages/contract-cli/package.json +++ b/packages/contract-cli/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-contract", - "version": "1.8.10", + "version": "1.8.11", "description": "JS API / command line tool to generate the contract.json for jsonql", "main": "index.js", "files": [ @@ -55,14 +55,14 @@ "fs-extra": "^8.1.0", "glob": "^7.1.6", "jsdoc-api": "^5.0.4", - "jsonql-constants": "^1.9.10", - "jsonql-errors": "^1.1.10", - "jsonql-params-validator": "^1.6.0", - "jsonql-utils": "^1.1.3", + "jsonql-constants": "^2.0.4", + "jsonql-errors": "^1.2.1", + "jsonql-params-validator": "^1.6.1", + "jsonql-utils": "^1.2.4", "kefir": "^3.8.6", "lodash": "^4.17.15", "nb-split-tasks": "^0.6.0", - "yargs": "^15.3.0" + "yargs": "^15.3.1" }, "devDependencies": { "ava": "^3.5.0", diff --git a/packages/contract-cli/src/generator/generate-output.js b/packages/contract-cli/src/generator/generate-output.js index c2d4e692..1f40fbe4 100644 --- a/packages/contract-cli/src/generator/generate-output.js +++ b/packages/contract-cli/src/generator/generate-output.js @@ -1,19 +1,17 @@ // the final step to generate output const { RETURN_AS_JSON } = require('jsonql-constants') -const { keepOrCleanContract, isContractExisted, writeFileOut } = require('./files-op') +const { keepOrCleanContract, writeFileOut } = require('./files-op') const { mutateContract } = require('./helpers') const { join } = require('path') /** * Generate the final contract output to file - * @param {string} sourceType what type of file we are dealing with * @param {object} config output directory * @param {object} contract processed result - * @param {boolean|object} [rawData=false] the raw contract data for ES6 create files * @return {boolean} true on success */ -const generateOutput = function(sourceType, config, contract, rawData = false) { +const generateOutput = function(config, contract) { // this return a promise interface - const { outputFilename, contractDir, resolverDir } = config; + const { outputFilename, contractDir } = config // resolverDir const dist = join(contractDir, outputFilename) // keep or remove the existing contract file return keepOrCleanContract(config, dist) diff --git a/packages/contract-cli/src/generator/index.js b/packages/contract-cli/src/generator/index.js index d5a168c5..c882e00a 100644 --- a/packages/contract-cli/src/generator/index.js +++ b/packages/contract-cli/src/generator/index.js @@ -46,10 +46,8 @@ const banner = config => { */ const callPublicGenerator = (config, contract) => ( generateOutput( - contract.sourceType, merge({}, config, { outputFilename: PUBLIC_CONTRACT_FILE_NAME }), - publicContractGenerator(config, contract), - contract // <-- this is when ES6 module require to generate import export files + publicContractGenerator(config, contract) ) ) diff --git a/packages/contract-cli/src/utils.js b/packages/contract-cli/src/utils.js index 4155acb2..c0775241 100644 --- a/packages/contract-cli/src/utils.js +++ b/packages/contract-cli/src/utils.js @@ -1,6 +1,6 @@ // some utils methods const fsx = require('fs-extra') -const { join, extname, resolve } = require('path') +const { extname, resolve } = require('path') const { isObject } = require('jsonql-params-validator') // we keep the lodash reference for chain later const { transform } = require('lodash') @@ -48,18 +48,18 @@ const getConfigFromArgs = (config, cmd) => ( if (key === '_') { switch (cmd) { case 'create': - let [inDir, outDir] = value; - result.inDir = inDir; - result.outDir = outDir; - break; + let [inDir, outDir] = value + result.inDir = inDir + result.outDir = outDir + break case 'remote': // @TODO throw new Error('Not support at the moment!') - break; + case 'config': // we don't need to do anything here // console.log('config', key, value) - break; + break } } else { result[key] = value @@ -81,7 +81,7 @@ const applyDefaultOptions = (config, cmd = false) => ( if (config.public === 'true' || config.public === 1 || config.public === '1') { config.public = true; // because it might be a string true } - return config; + return config }) .then(checkForConfigFile) .then(checkOptions) -- Gitee From 04e48967cdfed1f0da6892d1939fac01994ca560 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 20:09:19 +0800 Subject: [PATCH 56/66] update the public generator public clean up --- .../contract-cli/src/public-contract/index.js | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/packages/contract-cli/src/public-contract/index.js b/packages/contract-cli/src/public-contract/index.js index 03b6060f..d63f45eb 100644 --- a/packages/contract-cli/src/public-contract/index.js +++ b/packages/contract-cli/src/public-contract/index.js @@ -5,7 +5,8 @@ const { merge } = require('lodash') const { JsonqlError } = require('jsonql-errors') const { SOCKET_NAME, - QUERY_NAME + QUERY_NAME, + AUTH_NAME } = require('jsonql-constants') const { getDebug } = require('../utils') @@ -30,25 +31,30 @@ const cleanForPublic = (json, config) => { // @ 1.7.6 this function move to the Koa instead // because we want to keep the data in the file only remove it when serving up // if (!contractWithDesc) { - // delete json[type][fn].description; + // delete json[type][fn].description // } } } // also if there is a validator field then delete it - if (json.auth[validatorHandlerName]) { - delete json.auth[validatorHandlerName] + if (json[AUTH_NAME][validatorHandlerName]) { + delete json[AUTH_NAME][validatorHandlerName] } // if it's not enableAuth then remove all of these if (!enableAuth) { - if (json.auth[loginHandlerName]) { - delete json.auth[loginHandlerName] + if (json[AUTH_NAME][loginHandlerName]) { + delete json[AUTH_NAME][loginHandlerName] } - if (json.auth[logoutHandlerName]) { - delete json.auth[logoutHandlerName] + if (json[AUTH_NAME][logoutHandlerName]) { + delete json[AUTH_NAME][logoutHandlerName] + } + // check if there is any socket auth + if (json[SOCKET_NAME] && json[SOCKET_NAME][AUTH_NAME]) { + if (json[SOCKET_NAME][AUTH_NAME][validatorHandlerName]) { + delete json[SOCKET_NAME][AUTH_NAME][validatorHandlerName] + } } } // don't need this in the public json - // debug(json.sourceType) delete json.sourceType // export return json @@ -90,8 +96,6 @@ function processSocketContract(contractJson, helloContract) { return contractJson } - - /** * add an expired timstamp to the public contract * @param {object} config configuration @@ -109,6 +113,7 @@ function getExpired(config, contractJson) { } /** + * the actual public contract generator * @param {object} config the original config * @param {object} contractJson the raw json file * @return {string} json -- Gitee From 87abc3fbc54fd92912586eb496b3aaa7867dfdc3 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 20:16:19 +0800 Subject: [PATCH 57/66] Update all the generateOutput interface --- packages/contract-cli/cli.js | 6 +++--- packages/contract-cli/src/generator/generate-output.js | 6 ++++++ packages/contract-cli/src/generator/index.js | 2 +- packages/contract-cli/src/options.js | 3 ++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/contract-cli/cli.js b/packages/contract-cli/cli.js index a9f4b32a..b2931c9d 100755 --- a/packages/contract-cli/cli.js +++ b/packages/contract-cli/cli.js @@ -12,9 +12,9 @@ const { checkFile, watcher } = require('./src') -const { KEY_WORD } = require('jsonql-constants') -const { join } = require('path') -const debug = require('debug')('jsonql-contract:cli') +// const { KEY_WORD } = require('jsonql-constants') +// const { join } = require('path') +// const debug = require('debug')('jsonql-contract:cli') /** * wrapper for easily to call diff --git a/packages/contract-cli/src/generator/generate-output.js b/packages/contract-cli/src/generator/generate-output.js index 1f40fbe4..bd2bc979 100644 --- a/packages/contract-cli/src/generator/generate-output.js +++ b/packages/contract-cli/src/generator/generate-output.js @@ -3,6 +3,9 @@ const { RETURN_AS_JSON } = require('jsonql-constants') const { keepOrCleanContract, writeFileOut } = require('./files-op') const { mutateContract } = require('./helpers') const { join } = require('path') +const debug = require('debug')('jsonql-contract:generate-output') + + /** * Generate the final contract output to file * @param {object} config output directory @@ -10,6 +13,9 @@ const { join } = require('path') * @return {boolean} true on success */ const generateOutput = function(config, contract) { + + debug('generateOutput', config) + // this return a promise interface const { outputFilename, contractDir } = config // resolverDir const dist = join(contractDir, outputFilename) diff --git a/packages/contract-cli/src/generator/index.js b/packages/contract-cli/src/generator/index.js index c882e00a..6a271dac 100644 --- a/packages/contract-cli/src/generator/index.js +++ b/packages/contract-cli/src/generator/index.js @@ -64,7 +64,7 @@ const generateNewContract = (config) => { // we can get the sourceType from the contract return callPublicGenerator(config, contract) } - return generateOutput(sourceType, config, contract) + return generateOutput(config, contract) }) } diff --git a/packages/contract-cli/src/options.js b/packages/contract-cli/src/options.js index f1297f30..2c1fc3fe 100644 --- a/packages/contract-cli/src/options.js +++ b/packages/contract-cli/src/options.js @@ -49,7 +49,7 @@ const defaultOptions = { // file or json returnAs: createConfig(RETURN_AS_FILE, STRING_TYPE, {[ENUM_KEY]: RETURN_AS_ENUM}), // we need to force it to use useDoc = true for using jsdoc API now - useDoc: constructConfig(true, BOOLEAN_TYPE), // @TODO remove this later + // useDoc: constructConfig(true, BOOLEAN_TYPE), // @TODO remove this later // there will be cjs, es, ts for different parser jsType: constructConfig(CJS_TYPE , STRING_TYPE, false, ACCEPTED_JS_TYPES), // matching the name across the project - the above two will become alias to this @@ -71,6 +71,7 @@ const defaultOptions = { configFile: createConfig(false, [STRING_TYPE], {[OPTIONAL_KEY]: true, [ALIAS_KEY]: 'c'}), announceUrl: createConfig(false, [STRING_TYPE], {[OPTIONAL_KEY]: true, [ALIAS_KEY]: 'a'}), logDirectory: constructConfig(false, [STRING_TYPE], true), + // @TODO do we still need this one? tmpDir: createConfig(join(BASE_DIR, 'tmp'), [STRING_TYPE]), // ported from jsonql-koa buildContractOnStart: constructConfig(false, [BOOLEAN_TYPE], true), -- Gitee From 58c361dee64f96577be473d1f59dbe80cb767729 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 20:24:18 +0800 Subject: [PATCH 58/66] clean up the jsdoc methods --- packages/contract-cli/src/ast/jsdoc.js | 38 +++++++++---------- .../tests/contract-with-doc.test.js | 20 +++++----- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/packages/contract-cli/src/ast/jsdoc.js b/packages/contract-cli/src/ast/jsdoc.js index 45240bd5..d3bf75e1 100644 --- a/packages/contract-cli/src/ast/jsdoc.js +++ b/packages/contract-cli/src/ast/jsdoc.js @@ -1,23 +1,23 @@ // using jsdoc-cli to read the file and get additional properties // @TODO we still need to handle the @callback tag for function parameter // http://usejsdoc.org/tags-param.html -const { join } = require('path') +// const { join } = require('path') const { inspect } = require('util') -const fs = require('fs-extra') +// const fs = require('fs-extra') const jsdoc = require('jsdoc-api') const debug = require('debug')('jsonql-contract:jsdoc-api') const { DEFAULT_TYPE, SUPPORTED_TYPES, NUMBER_TYPES, - NUMBER_TYPE + NUMBER_TYPE, + OBJECT_TYPE, + ARRAY_TYPE_LFT, + ARRAY_TYPE_RGT } = require('jsonql-constants') const { JsonqlError } = require('jsonql-errors') -const { keyBy, some, result, groupBy, size, indexOf } = require('lodash') +const { some, groupBy, indexOf } = require('lodash') -const OBJECT_TYPE = 'object'; -const LFT = 'array.<'; -const RHT = '>'; /** * small helper to output all the debug code in details */ @@ -32,7 +32,7 @@ const normalizeType = function(type) { const t = type.toLowerCase(); // is wildcard if (t === '*') { - return DEFAULT_TYPE; + return DEFAULT_TYPE } // normal check if (indexOf(SUPPORTED_TYPES, t) > -1) { @@ -47,9 +47,9 @@ const normalizeType = function(type) { if (t.indexOf('array.') > -1) { // debug('Array type here', t); // process the type within the array - const _type = t.replace(LFT,'').replace(RHT,'') + const _type = t.replace(ARRAY_TYPE_LFT,'').replace(ARRAY_TYPE_RGT,'') // call myself again - return LFT + normalizeType(_type) + RHT + return ARRAY_TYPE_LFT + normalizeType(_type) + ARRAY_TYPE_RGT } // and finally if we couldn't figure it out then it will all be any type! debug(`Raised a warning here, the ${type} / ${t} is unknown to use!`) @@ -67,8 +67,8 @@ const transformName = function(params) { // only support one level at the moment // actually that is the same with Typescript Interface const names = p.name.split('.') - p.name = names[1]; - p.parent = names[0]; + p.name = names[1] + p.parent = names[0] } return p }) @@ -96,7 +96,7 @@ const foldParams = function(params) { const _params = transformName(params) const children = getChildren(_params) // capture to validate if there is any children left - const len = size(children) + // const len = size(children) let ctn = 0 // @TODO here if we just reduce the array and it's done // but the problem is if there is an wrong comment with orphan @@ -120,7 +120,7 @@ const foldParams = function(params) { * @return {object} result from jsdoc */ const explainSync = function(source) { - return jsdoc.explainSync({source}) + return jsdoc.explainSync({ source }) } /** @@ -175,10 +175,10 @@ const search = function(output, name = '') { }).map(res => { let resolverName = res.meta.code.value || res.meta.code.name - debug(`----------------${resolverName}---------------------`) - debug('res.meta', detailOut(res.meta)) - debug('res.params', detailOut(res.params)) - debug('res.returns', detailOut(res.returns)) + // debug(`----------------${resolverName}---------------------`) + // debug('res.meta', detailOut(res.meta)) + // debug('res.params', detailOut(res.params)) + // debug('res.returns', detailOut(res.returns)) return { name: resolverName, @@ -220,7 +220,7 @@ const clearForOutput = function(result, name) { console.error(`res.params it not defined?`, detailOut(res)) throw new Error(`Could not parse the jsdoc for ${name}! res.params ${res.params}`) } - return res; + return res } else { console.error('jsdoc return result', detailOut(result)) throw new JsonqlError(`${name} jsdoc parsing result is unexpected, did the programmer wrote comment correctly?`, result) diff --git a/packages/contract-cli/tests/contract-with-doc.test.js b/packages/contract-cli/tests/contract-with-doc.test.js index 46db62e0..8e096677 100644 --- a/packages/contract-cli/tests/contract-with-doc.test.js +++ b/packages/contract-cli/tests/contract-with-doc.test.js @@ -28,29 +28,29 @@ test.after(async t => { test('The contract.json should contain jsdoc information', async t => { - t.is(true, fsx.existsSync( baseContractFile )) - const json = t.context.contract; + t.truthy(fsx.existsSync( baseContractFile )) + const json = t.context.contract // check the properties - t.is(true, typeof json.query.getOthers === 'object', 'Test if we have getOthers') - t.is(true, json.query.getOthers.params[0].type[0] === DEFAULT_TYPE , 'Test if there is a param of DEFAULT_TYPE') - t.is(true, json.query.getOthers.returns[0].type[0] === 'object', 'Test to see if have an object type') + t.true(typeof json.query.getOthers === 'object', 'Test if we have getOthers') + t.true(json.query.getOthers.params[0].type[0] === DEFAULT_TYPE , 'Test if there is a param of DEFAULT_TYPE') + t.true(json.query.getOthers.returns[0].type[0] === 'object', 'Test to see if have an object type') }) test('The mutation should able to fold the key under the same name', async t => { const json = t.context.contract; const baseFn = json.mutation.setDetailObj.params; - t.is(true, baseFn[0].name === 'payload', 'Test to see if we have payload') - t.is(true, Array.isArray(baseFn[0].keys), 'Test to see if we capture the keys of the object') - t.is(true, baseFn[1].name === 'condition' && baseFn[1].type[0] === 'object', 'Test to see if we have condition') - t.is(true, baseFn[1].keys[0].name === 'id', 'Test to see if the keys has name id') + t.true(baseFn[0].name === 'payload', 'Test to see if we have payload') + t.true(Array.isArray(baseFn[0].keys), 'Test to see if we capture the keys of the object') + t.true(baseFn[1].name === 'condition' && baseFn[1].type[0] === 'object', 'Test to see if we have condition') + t.true(baseFn[1].keys[0].name === 'id', 'Test to see if the keys has name id') }) test('The contract should contain socket information', async t => { const json = t.context.contract; const socket = json.socket; - t.is(true, typeof socket === 'object') + t.true(typeof socket === 'object') t.truthy(socket.chatroom.namespace) }) -- Gitee From c4e8f26a7e70a3523d025e6d96ac0f37f316d9ae Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 21:04:02 +0800 Subject: [PATCH 59/66] clean up some of the code but could not find where is the bug about the missing auth stuff --- .../contract-cli/src/generator/get-resolver.js | 14 +++++++++----- packages/contract-cli/src/get-paths.js | 8 ++++---- packages/contract-cli/src/utils.js | 12 +++++------- .../contract-cli/tests/contract-with-doc.test.js | 14 +++++++------- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/packages/contract-cli/src/generator/get-resolver.js b/packages/contract-cli/src/generator/get-resolver.js index 5fa417dd..bbf05364 100644 --- a/packages/contract-cli/src/generator/get-resolver.js +++ b/packages/contract-cli/src/generator/get-resolver.js @@ -2,9 +2,13 @@ const fsx = require('fs-extra') const { basename } = require('path') // join, const { compact } = require('lodash') -const { INDEX_KEY } = require('jsonql-constants') +const { + INDEX_KEY, + QUERY_NAME, + MUTATION_NAME, + AUTH_NAME +} = require('jsonql-constants') const { - // addPublicKey, inTypesArray, isAuthType, checkIfIsPublic, @@ -128,9 +132,9 @@ function processResolverToContract(type, name, file, public, namespace, sourceTy */ function getContractBase(sourceType) { return { - query: {}, - mutation: {}, - auth: {}, + [QUERY_NAME]: {}, + [MUTATION_NAME]: {}, + [AUTH_NAME]: {}, timestamp: getTimestamp(), sourceType: sourceType } diff --git a/packages/contract-cli/src/get-paths.js b/packages/contract-cli/src/get-paths.js index 62d60424..10b0dbc0 100755 --- a/packages/contract-cli/src/get-paths.js +++ b/packages/contract-cli/src/get-paths.js @@ -17,19 +17,19 @@ function getPaths(argv) { if (argv.contractDir) { argv.contractDir = resolve(argv.contractDir) } else { - argv.contractDir = baseDir; + argv.contractDir = baseDir } argv.resolverDir = resolve(argv.resolverDir) return resolver(argv); // just return it } else if (argv._) { - const args = argv._; + const args = argv._ if (args[0]) { return resolver({ resolverDir: resolve(args[0]), contractDir: args[1] ? resolve(args[1]) : baseDir, // raw: argv.raw, if they are using command line raw is not available as option public: argv.public - }); + }) } } rejecter('You need to provide the input path!') @@ -55,7 +55,7 @@ function checkInputPath(paths) { rejecter(e) } } - }); + }) } // main diff --git a/packages/contract-cli/src/utils.js b/packages/contract-cli/src/utils.js index c0775241..0eb93484 100644 --- a/packages/contract-cli/src/utils.js +++ b/packages/contract-cli/src/utils.js @@ -2,15 +2,13 @@ const fsx = require('fs-extra') const { extname, resolve } = require('path') const { isObject } = require('jsonql-params-validator') -// we keep the lodash reference for chain later +const { JsonqlError } = require('jsonql-errors') +const { timestamp } = require('jsonql-utils') const { transform } = require('lodash') -const debug = require('debug') -// const { KEY_WORD } = require('jsonql-constants'); + const checkOptions = require('./options') -const { JsonqlError } = require('jsonql-errors') -// timestamp with mil seconds -const { timestamp } = require('jsonql-utils') +const debug = require('debug') const MODULE_NAME = 'jsonql-contract' const getTimestamp = () => timestamp(true) @@ -79,7 +77,7 @@ const applyDefaultOptions = (config, cmd = false) => ( .then(config => { getDebug('applyDefaultOptions')('show config', config) if (config.public === 'true' || config.public === 1 || config.public === '1') { - config.public = true; // because it might be a string true + config.public = true // because it might be a string true } return config }) diff --git a/packages/contract-cli/tests/contract-with-doc.test.js b/packages/contract-cli/tests/contract-with-doc.test.js index 8e096677..a306d950 100644 --- a/packages/contract-cli/tests/contract-with-doc.test.js +++ b/packages/contract-cli/tests/contract-with-doc.test.js @@ -5,7 +5,7 @@ const { join } = require('path') const generator = require('../index') const resolverDir = join(__dirname, 'fixtures', 'resolvers') const contractDir = join(__dirname, 'fixtures', 'tmp', 'doc') -// const debug = require('debug')('jsonql-contract:test:generator') +const debug = require('debug')('jsonql-contract:test:generator') const fsx = require('fs-extra') const baseContractFile = join(contractDir, 'contract.json') // const publicContractFile = join(contractDir, 'public-contract.json') @@ -23,7 +23,7 @@ test.before(async t => { }) test.after(async t => { - fsx.removeSync(contractDir) + // fsx.removeSync(contractDir) }) test('The contract.json should contain jsdoc information', async t => { @@ -37,8 +37,8 @@ test('The contract.json should contain jsdoc information', async t => { }) test('The mutation should able to fold the key under the same name', async t => { - const json = t.context.contract; - const baseFn = json.mutation.setDetailObj.params; + const json = t.context.contract + const baseFn = json.mutation.setDetailObj.params t.true(baseFn[0].name === 'payload', 'Test to see if we have payload') t.true(Array.isArray(baseFn[0].keys), 'Test to see if we capture the keys of the object') @@ -55,13 +55,13 @@ test('The contract should contain socket information', async t => { }) test('There should be a logout method', t => { - const json = t.context.contract; - // debug(json); + const json = t.context.contract + debug(json) t.deepEqual([], json.auth.logout.params) }) test('There should be a method from the private folder', t => { - const json = t.context.contract; + const json = t.context.contract // private-fn-in-folder t.truthy( json.query.privateFnInFolder ) t.truthy( json.query.privateFn ) -- Gitee From 8f8f52a92de7c90d85a261269e997a85a2bb9b30 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 22:10:36 +0800 Subject: [PATCH 60/66] Fix the auth generator because of the wrong constants names --- .../contract-cli/src/generator/helpers.js | 15 ++++++++------- packages/contract-cli/src/generator/index.js | 7 ++++--- .../src/generator/read-files-out-contract.js | 1 + packages/contract-cli/src/options.js | 19 ++++++++++--------- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/packages/contract-cli/src/generator/helpers.js b/packages/contract-cli/src/generator/helpers.js index 4b9bfaf4..57f976d1 100644 --- a/packages/contract-cli/src/generator/helpers.js +++ b/packages/contract-cli/src/generator/helpers.js @@ -2,14 +2,11 @@ const fsx = require('fs-extra') const { merge, extend, camelCase } = require('lodash') const { isObject } = require('jsonql-params-validator') -const { isContract } = require('jsonql-utils') // isObjectHasKey, +const { isContract, inArray } = require('jsonql-utils') // isObjectHasKey, const { RESOLVER_TYPES, AUTH_TYPE, SOCKET_NAME, - // PUBLIC_KEY, - // QUERY_NAME, - // MUTATION_NAME, JSONQL_PATH, PRIVATE_KEY } = require('jsonql-constants') @@ -42,13 +39,17 @@ const inTypesArray = (item) => ( */ const isAuthType = function(type, file, config) { let resolverName = camelCase(file) + if (!AUTH_TYPE_METHODS) { const { loginHandlerName, logoutHandlerName, validatorHandlerName } = config AUTH_TYPE_METHODS = [loginHandlerName, logoutHandlerName, validatorHandlerName] } - // debug('AUTH_TYPE_METHODS', AUTH_TYPE_METHODS) - // debug('AUTH_TYPE_METHODS', resolverName, AUTH_TYPE_METHODS) - return type === AUTH_TYPE && !!AUTH_TYPE_METHODS.filter(method => resolverName === method).length + + if (type === AUTH_TYPE ) { + debug('isAuthType', resolverName, AUTH_TYPE_METHODS) + return inArray(AUTH_TYPE_METHODS, resolverName) + } + return false } /** diff --git a/packages/contract-cli/src/generator/index.js b/packages/contract-cli/src/generator/index.js index 6a271dac..25ee7d4a 100644 --- a/packages/contract-cli/src/generator/index.js +++ b/packages/contract-cli/src/generator/index.js @@ -26,13 +26,14 @@ let ctn = 0 const banner = config => { // debug('received config', config); if (config.banner === true) { - ++ctn; + ++ctn console.log( `[${ctn}] in: `, colors.cyan(`${config.resolverDir}`), - 'out: ', + '\nout: ', colors.green(`${config.contractDir}`), - `[${config.returnAs} output] ${config.public ? '[public]': ''}` + `\n[${config.returnAs} output] ${config.public ? '[public]': ''}`, + `${config.enableAuth ? '[auth]': '' }` ) } return ctn diff --git a/packages/contract-cli/src/generator/read-files-out-contract.js b/packages/contract-cli/src/generator/read-files-out-contract.js index f0d71d73..b1a98095 100644 --- a/packages/contract-cli/src/generator/read-files-out-contract.js +++ b/packages/contract-cli/src/generator/read-files-out-contract.js @@ -27,6 +27,7 @@ function getResolverFiles(resolverDir, fileType) { debug(`File read error!`, err) return rejecter(err) } + // debug('getResolverFiles', files) resolver(files) }) }) diff --git a/packages/contract-cli/src/options.js b/packages/contract-cli/src/options.js index 2c1fc3fe..37216699 100644 --- a/packages/contract-cli/src/options.js +++ b/packages/contract-cli/src/options.js @@ -22,9 +22,9 @@ const { ENUM_KEY, RETURN_AS_FILE, RETURN_AS_ENUM, - LOGIN_NAME, - LOGOUT_NAME, - VALIDATOR_NAME, + LOGIN_FN_NAME, + LOGOUT_FN_NAME, + VALIDATOR_FN_NAME, DEFAULT_CONTRACT_FILE_NAME } = require('jsonql-constants') @@ -35,15 +35,15 @@ const constProps = { outputFilename: DEFAULT_CONTRACT_FILE_NAME } -const defaultOptions = { +const checkMap = { // give the contract an expired time expired: createConfig(0, [NUMBER_TYPE]), // passing extra props to the contract.json extraContractProps: createConfig(false, [OBJECT_TYPE], {[OPTIONAL_KEY]: true}), // Auth related props - loginHandlerName: createConfig(LOGIN_NAME, [STRING_TYPE]), - logoutHandlerName: createConfig(LOGOUT_NAME, [STRING_TYPE]), - validatorHandlerName: createConfig(VALIDATOR_NAME, [STRING_TYPE, BOOLEAN_TYPE]), + loginHandlerName: createConfig(LOGIN_FN_NAME, [STRING_TYPE]), + logoutHandlerName: createConfig(LOGOUT_FN_NAME, [STRING_TYPE]), + validatorHandlerName: createConfig(VALIDATOR_FN_NAME, [STRING_TYPE, BOOLEAN_TYPE]), enableAuth: createConfig(false, BOOLEAN_TYPE, {[ALIAS_KEY]: 'auth'}), // file or json @@ -80,5 +80,6 @@ const defaultOptions = { // add 1.8.7 to determine if we clean out the contract folder or not development: createConfig(false, [BOOLEAN_TYPE]) } -// export it -module.exports = config => checkConfigAsync(config, defaultOptions, constProps) + +// export it as named module +module.exports = config => checkConfigAsync(config, checkMap, constProps) -- Gitee From c2629ce7f384b09c344c40066436e960f26652f0 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 22:24:04 +0800 Subject: [PATCH 61/66] contract-cli fixed --- packages/contract-cli/src/generator/helpers.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/contract-cli/src/generator/helpers.js b/packages/contract-cli/src/generator/helpers.js index 57f976d1..1f8f0811 100644 --- a/packages/contract-cli/src/generator/helpers.js +++ b/packages/contract-cli/src/generator/helpers.js @@ -45,11 +45,7 @@ const isAuthType = function(type, file, config) { AUTH_TYPE_METHODS = [loginHandlerName, logoutHandlerName, validatorHandlerName] } - if (type === AUTH_TYPE ) { - debug('isAuthType', resolverName, AUTH_TYPE_METHODS) - return inArray(AUTH_TYPE_METHODS, resolverName) - } - return false + return type === AUTH_TYPE && inArray(AUTH_TYPE_METHODS, resolverName) } /** -- Gitee From 7740f7f2cd6f8df7dc14fb4d1ff1dded6482ab52 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 22:30:48 +0800 Subject: [PATCH 62/66] Add a dummy validator to check if its working correctly --- packages/contract-cli/tests/contract-with-doc.test.js | 2 +- .../fixtures/resolvers/socket/auth/validator/index.js | 8 ++++++++ packages/contract-cli/tests/generator.test.js | 8 +++++++- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 packages/contract-cli/tests/fixtures/resolvers/socket/auth/validator/index.js diff --git a/packages/contract-cli/tests/contract-with-doc.test.js b/packages/contract-cli/tests/contract-with-doc.test.js index a306d950..0c6391f1 100644 --- a/packages/contract-cli/tests/contract-with-doc.test.js +++ b/packages/contract-cli/tests/contract-with-doc.test.js @@ -23,7 +23,7 @@ test.before(async t => { }) test.after(async t => { - // fsx.removeSync(contractDir) + fsx.removeSync(contractDir) }) test('The contract.json should contain jsdoc information', async t => { diff --git a/packages/contract-cli/tests/fixtures/resolvers/socket/auth/validator/index.js b/packages/contract-cli/tests/fixtures/resolvers/socket/auth/validator/index.js new file mode 100644 index 00000000..056d22a3 --- /dev/null +++ b/packages/contract-cli/tests/fixtures/resolvers/socket/auth/validator/index.js @@ -0,0 +1,8 @@ +/** + * socket auth validator interceptor + * @param {*} req request object + * @return {boolean} + */ +module.exports = function validator(req) { + return req ? true : false +} \ No newline at end of file diff --git a/packages/contract-cli/tests/generator.test.js b/packages/contract-cli/tests/generator.test.js index 322fb17b..dfc132d0 100755 --- a/packages/contract-cli/tests/generator.test.js +++ b/packages/contract-cli/tests/generator.test.js @@ -51,7 +51,13 @@ test.serial('There should be a contract.json output to the contractDir', async t contractDir, enableAuth: true }) - t.is(true, fsx.existsSync( baseContractFile )) + + debug(result) + + t.truthy( fsx.existsSync( baseContractFile )) + + + }) // serial. test.only('Should able to create a public-contract.json', async t => { -- Gitee From 8cfc6940fad5fd2ea2b8eba2794b47d274a24dfc Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 22:35:03 +0800 Subject: [PATCH 63/66] add disconnectHandlerName to the options list --- .../contract-cli/src/generator/get-socket-auth-resolver.js | 2 ++ packages/contract-cli/src/options.js | 6 ++++-- packages/contract-cli/tests/socket.test.js | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/contract-cli/src/generator/get-socket-auth-resolver.js b/packages/contract-cli/src/generator/get-socket-auth-resolver.js index 0fa32a70..8129b977 100644 --- a/packages/contract-cli/src/generator/get-socket-auth-resolver.js +++ b/packages/contract-cli/src/generator/get-socket-auth-resolver.js @@ -40,11 +40,13 @@ function filterAuthFiles(config, authFiles, fileExt = EXT) { const { loginHandlerName, logoutHandlerName, + validatorHandlerName, disconnectHandlerName } = config const targets = [ loginHandlerName, logoutHandlerName, + validatorHandlerName, disconnectHandlerName ] diff --git a/packages/contract-cli/src/options.js b/packages/contract-cli/src/options.js index 37216699..f33ed1a7 100644 --- a/packages/contract-cli/src/options.js +++ b/packages/contract-cli/src/options.js @@ -25,6 +25,7 @@ const { LOGIN_FN_NAME, LOGOUT_FN_NAME, VALIDATOR_FN_NAME, + DISCONNECT_FN_NAME, DEFAULT_CONTRACT_FILE_NAME } = require('jsonql-constants') @@ -43,8 +44,9 @@ const checkMap = { // Auth related props loginHandlerName: createConfig(LOGIN_FN_NAME, [STRING_TYPE]), logoutHandlerName: createConfig(LOGOUT_FN_NAME, [STRING_TYPE]), - validatorHandlerName: createConfig(VALIDATOR_FN_NAME, [STRING_TYPE, BOOLEAN_TYPE]), - + validatorHandlerName: createConfig(VALIDATOR_FN_NAME, [STRING_TYPE]), + disconnectHandlerName: createConfig(DISCONNECT_FN_NAME, [STRING_TYPE]), + enableAuth: createConfig(false, BOOLEAN_TYPE, {[ALIAS_KEY]: 'auth'}), // file or json returnAs: createConfig(RETURN_AS_FILE, STRING_TYPE, {[ENUM_KEY]: RETURN_AS_ENUM}), diff --git a/packages/contract-cli/tests/socket.test.js b/packages/contract-cli/tests/socket.test.js index 67539a8b..7a62bd48 100644 --- a/packages/contract-cli/tests/socket.test.js +++ b/packages/contract-cli/tests/socket.test.js @@ -42,7 +42,9 @@ test.cb(`It should able to generate partial contract for socket auth`, t => { getSocketAuthResolver(t.context.config, resolverDir) .then(contract => { + debug('partial contract', contract) + t.truthy(contract) t.end() }) -- Gitee From fe6ca9af67a3b6a576e089bcd85b6f66761c9d8f Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 18 Mar 2020 22:46:41 +0800 Subject: [PATCH 64/66] fix the interceptor name when its inside a folder --- .../src/generator/get-socket-auth-resolver.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/contract-cli/src/generator/get-socket-auth-resolver.js b/packages/contract-cli/src/generator/get-socket-auth-resolver.js index 8129b977..2b0a6d7c 100644 --- a/packages/contract-cli/src/generator/get-socket-auth-resolver.js +++ b/packages/contract-cli/src/generator/get-socket-auth-resolver.js @@ -3,8 +3,8 @@ // its mainly for internal use const fsx = require('fs-extra') const debug = require('debug')('jsonql-contract:generator:get-socket-auth-resolver') -const { join, basename } = require('path') -const { SOCKET_NAME, AUTH_NAME, EXT } = require('jsonql-constants') +const { join, sep, dirname, basename } = require('path') +const { SOCKET_NAME, AUTH_NAME, EXT, INDEX_KEY } = require('jsonql-constants') const { getResolverFiles } = require('./read-files-out-contract') const { inArray } = require('jsonql-params-validator') const { getSourceType } = require('./get-source-type') @@ -52,11 +52,19 @@ function filterAuthFiles(config, authFiles, fileExt = EXT) { return authFiles .map(file => { - const name = basename(file).replace('.'+fileExt, '') + const name = basename(file).replace('.' + fileExt, '') + // need to take the folder name in if it's an index file + if (name === INDEX_KEY) { + const dir = dirname(file).split(sep) + + return {[ dir[dir.length - 1] ]: file} + } + return {[name]: file} }) .filter(fileObj => { const name = Object.keys(fileObj)[0] + return inArray(targets, name) }) .reduce((a,b) => Object.assign(a, b), {}) -- Gitee From 3b983159d680db8ab782384191c80dc6d3971c91 Mon Sep 17 00:00:00 2001 From: joelchu Date: Thu, 19 Mar 2020 00:34:47 +0800 Subject: [PATCH 65/66] Fix the existing test --- .../src/generator/generate-output.js | 7 +++- .../src/generator/get-socket-auth-resolver.js | 38 +++++++++++++++---- packages/contract-cli/tests/socket.test.js | 6 ++- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/packages/contract-cli/src/generator/generate-output.js b/packages/contract-cli/src/generator/generate-output.js index bd2bc979..6e726c86 100644 --- a/packages/contract-cli/src/generator/generate-output.js +++ b/packages/contract-cli/src/generator/generate-output.js @@ -1,6 +1,7 @@ // the final step to generate output const { RETURN_AS_JSON } = require('jsonql-constants') const { keepOrCleanContract, writeFileOut } = require('./files-op') +const { processSocketAuth } = require('./get-socket-auth-resolver') const { mutateContract } = require('./helpers') const { join } = require('path') const debug = require('debug')('jsonql-contract:generate-output') @@ -14,14 +15,16 @@ const debug = require('debug')('jsonql-contract:generate-output') */ const generateOutput = function(config, contract) { - debug('generateOutput', config) + debug('generateOutput configuration', config) // this return a promise interface const { outputFilename, contractDir } = config // resolverDir const dist = join(contractDir, outputFilename) // keep or remove the existing contract file return keepOrCleanContract(config, dist) - .then(() => mutateContract(config, contract)) + // @1.9.0 add the socket auth part + .then(() => processSocketAuth(config, contract)) + .then(newContract => mutateContract(config, newContract)) .then(finalContract => ( writeFileOut(dist, finalContract) .then(() => ( diff --git a/packages/contract-cli/src/generator/get-socket-auth-resolver.js b/packages/contract-cli/src/generator/get-socket-auth-resolver.js index 2b0a6d7c..4943353c 100644 --- a/packages/contract-cli/src/generator/get-socket-auth-resolver.js +++ b/packages/contract-cli/src/generator/get-socket-auth-resolver.js @@ -22,7 +22,7 @@ function getSocketAuthResolverFiles(resolverDir, fileExt = EXT) { if (fsx.existsSync(dir)) { return getResolverFiles(dir, fileExt) } - debug(`${dir} not existed!`) + debug(`${dir} does not existed!`) // we don't throw error here just return an empty result return Promise.resolve([]) } @@ -56,7 +56,7 @@ function filterAuthFiles(config, authFiles, fileExt = EXT) { // need to take the folder name in if it's an index file if (name === INDEX_KEY) { const dir = dirname(file).split(sep) - + return {[ dir[dir.length - 1] ]: file} } @@ -97,13 +97,13 @@ function processFileToContract(name, file, sourceType) { /** * The main method to generate the partial contract of the socket auth methods * @param {object} config configuration - * @param {string} resolverDir where the resolvers are * @param {string|boolean} [sourceType=null] what type of files are they ES6 or CS * @param {string} [fileExt=EXT] the file extension * @return {promise} resolve the socket auth partial contract */ -function getSocketAuthResolver(config, resolverDir, sourceType = null, fileExt = EXT) { - +function getSocketAuthResolver(config, sourceType = null, fileExt = EXT) { + const { resolverDir } = config + return getSocketAuthResolverFiles(resolverDir, fileExt) .then(files => filterAuthFiles(config, files, fileExt)) .then(fileObj => { @@ -129,13 +129,37 @@ function getSocketAuthResolver(config, resolverDir, sourceType = null, fileExt = true ) }) - .then(contract => ({[AUTH_NAME]: contract})) + .then(contract => ({ + [SOCKET_NAME]: { + [AUTH_NAME]: contract + } + })) +} + +/** + * This will be the main interface that insert into the generateOutput + * @param {object} config configuration + * @param {object} contract the already working contract + * @return {object} contract with the extra bit + */ +function processSocketAuth(config, contract) { + if (config[SOCKET_NAME] && config.enableAuth === true) { + const { sourceType } = contract + return getSocketAuthResolver(config, sourceType) + .then(partialContract => ( + merge({}, contract, partialContract) + )) + } + + return contract } + module.exports = { getSocketAuthResolver, filterAuthFiles, - getSocketAuthResolverFiles + getSocketAuthResolverFiles, + processSocketAuth } diff --git a/packages/contract-cli/tests/socket.test.js b/packages/contract-cli/tests/socket.test.js index 7a62bd48..4f68c0a8 100644 --- a/packages/contract-cli/tests/socket.test.js +++ b/packages/contract-cli/tests/socket.test.js @@ -15,13 +15,15 @@ const getConfig = require('./fixtures/socket/config') const debug = require('debug')('jsonql-contract:test:socket') test.before(async t => { - t.context.config = await getConfig({enableAuth: true}) + t.context.config = await getConfig({ enableAuth: true, resolverDir }) }) test.cb(`It should able to return a list of socket auth files`, t => { t.plan(1) + debug('resolverdir', resolverDir) + getSocketAuthResolverFiles(resolverDir) .then(files => { @@ -40,7 +42,7 @@ test.cb(`It should able to return a list of socket auth files`, t => { test.cb(`It should able to generate partial contract for socket auth`, t => { t.plan(1) - getSocketAuthResolver(t.context.config, resolverDir) + getSocketAuthResolver(t.context.config) .then(contract => { debug('partial contract', contract) -- Gitee From 40231529fd45a670bb1290b4ff0ed3e4e38d24dd Mon Sep 17 00:00:00 2001 From: joelchu Date: Thu, 19 Mar 2020 11:09:24 +0800 Subject: [PATCH 66/66] Adding new contract key name for new features --- packages/constants/README.md | 5 ++ packages/constants/base.js | 27 ++++++--- packages/constants/browser.js | 8 ++- packages/constants/constants.json | 8 ++- packages/constants/index.js | 48 +++++++++------- packages/constants/main.js | 8 ++- packages/constants/package.json | 2 +- packages/constants/socket.js | 20 +++---- .../src/generator/get-socket-auth-resolver.js | 55 +++++++++---------- packages/contract-cli/tests/generator.test.js | 9 +-- packages/contract-cli/tests/socket.test.js | 42 ++++++++++++-- 11 files changed, 149 insertions(+), 83 deletions(-) diff --git a/packages/constants/README.md b/packages/constants/README.md index 9bf50ba6..9986af23 100755 --- a/packages/constants/README.md +++ b/packages/constants/README.md @@ -44,7 +44,12 @@ Please consult the detail break down below. - QUERY_NAME - MUTATION_NAME - SOCKET_NAME +- SOCKET_AUTH_NAME +- EXTERNAL_NAME +- INTERCEPTOR_NAME +- PLUGIN_NAME - CONTRACT_NAME +- MIDDLEWARE_NAME - RESOLVER_TYPES - PAYLOAD_PARAM_NAME - CONDITION_PARAM_NAME diff --git a/packages/constants/base.js b/packages/constants/base.js index 7f4508d1..3ed50cc9 100644 --- a/packages/constants/base.js +++ b/packages/constants/base.js @@ -38,11 +38,20 @@ export const SCRIPT_TYPE = 'script' export const QUERY_NAME = 'query' export const MUTATION_NAME = 'mutation' export const SOCKET_NAME = 'socket' +// we need to add a new field to the contract so it won't create confusion +export const SOCKET_AUTH_NAME = 'socket-auth' +// the following are for the next development features +export const EXTERNAL_NAME = 'external' +export const INTERCEPTOR_NAME = 'interceptor' +export const PLUGIN_NAME = 'plugin' export const CONTRACT_NAME = 'contract' +export const MIDDLEWARE_NAME = 'middleware' + export const RESOLVER_TYPES = [ - QUERY_NAME, - MUTATION_NAME, - SOCKET_NAME + QUERY_NAME, + MUTATION_NAME, + SOCKET_NAME, + SOCKET_AUTH_NAME ] // for calling the mutation export const PAYLOAD_PARAM_NAME = 'payload' // @TODO shortern them @@ -51,8 +60,8 @@ export const RESOLVER_PARAM_NAME = 'resolverName' export const QUERY_ARG_NAME = 'args' export const TIMESTAMP_PARAM_NAME = 'TS' export const MUTATION_ARGS = [ - RESOLVER_PARAM_NAME, - PAYLOAD_PARAM_NAME, + RESOLVER_PARAM_NAME, + PAYLOAD_PARAM_NAME, CONDITION_PARAM_NAME ] // new jsonp @@ -69,7 +78,7 @@ export const PRIVATE_KEY = 'private' // author export const AUTH_TYPE = 'auth' -export const AUTH_NAME = AUTH_TYPE // alias +export const AUTH_NAME = AUTH_TYPE // alias export const LOGIN_FN_NAME = 'login' // export const ISSUER_NAME = LOGIN_NAME // legacy issue need to replace them later export const LOGOUT_FN_NAME = 'logout' @@ -101,7 +110,7 @@ export const CJS_TYPE = 'cjs' export const ES_TYPE = 'es' export const TS_TYPE = 'ts' export const ACCEPTED_JS_TYPES = [ - CJS_TYPE, + CJS_TYPE, ES_TYPE ] // not accept this TS_TYPE at the moment @@ -109,7 +118,7 @@ export const ACCEPTED_JS_TYPES = [ export const RETURN_AS_FILE = 'file' export const RETURN_AS_JSON = 'json' export const RETURN_AS_ENUM = [ - RETURN_AS_FILE, + RETURN_AS_FILE, RETURN_AS_JSON ] @@ -121,7 +130,7 @@ export const SUCCESS_STATUS = 200 export const UNAUTHORIZED_STATUS = 401 export const FORBIDDEN_STATUS = 403 export const NOT_FOUND_STATUS = 404 -export const NOT_ACCEPTABLE_STATUS = 406 +export const NOT_ACCEPTABLE_STATUS = 406 export const SERVER_INTERNAL_STATUS = 500 // just whatever export const DEFAULT_PORT_NUM = 6557 diff --git a/packages/constants/browser.js b/packages/constants/browser.js index b3379baa..4d7678c6 100644 --- a/packages/constants/browser.js +++ b/packages/constants/browser.js @@ -23,11 +23,17 @@ var jsonqlConstants = { "QUERY_NAME": "query", "MUTATION_NAME": "mutation", "SOCKET_NAME": "socket", + "SOCKET_AUTH_NAME": "socket-auth", + "EXTERNAL_NAME": "external", + "INTERCEPTOR_NAME": "interceptor", + "PLUGIN_NAME": "plugin", "CONTRACT_NAME": "contract", + "MIDDLEWARE_NAME": "middleware", "RESOLVER_TYPES": [ "query", "mutation", - "socket" + "socket", + "socket-auth" ], "PAYLOAD_PARAM_NAME": "payload", "CONDITION_PARAM_NAME": "condition", diff --git a/packages/constants/constants.json b/packages/constants/constants.json index 5242ceb5..6b9048b9 100644 --- a/packages/constants/constants.json +++ b/packages/constants/constants.json @@ -23,11 +23,17 @@ "QUERY_NAME": "query", "MUTATION_NAME": "mutation", "SOCKET_NAME": "socket", + "SOCKET_AUTH_NAME": "socket-auth", + "EXTERNAL_NAME": "external", + "INTERCEPTOR_NAME": "interceptor", + "PLUGIN_NAME": "plugin", "CONTRACT_NAME": "contract", + "MIDDLEWARE_NAME": "middleware", "RESOLVER_TYPES": [ "query", "mutation", - "socket" + "socket", + "socket-auth" ], "PAYLOAD_PARAM_NAME": "payload", "CONDITION_PARAM_NAME": "condition", diff --git a/packages/constants/index.js b/packages/constants/index.js index 15237c0f..b996940f 100644 --- a/packages/constants/index.js +++ b/packages/constants/index.js @@ -40,11 +40,20 @@ export const SCRIPT_TYPE = 'script' export const QUERY_NAME = 'query' export const MUTATION_NAME = 'mutation' export const SOCKET_NAME = 'socket' +// we need to add a new field to the contract so it won't create confusion +export const SOCKET_AUTH_NAME = 'socket-auth' +// the following are for the next development features +export const EXTERNAL_NAME = 'external' +export const INTERCEPTOR_NAME = 'interceptor' +export const PLUGIN_NAME = 'plugin' export const CONTRACT_NAME = 'contract' +export const MIDDLEWARE_NAME = 'middleware' + export const RESOLVER_TYPES = [ - QUERY_NAME, - MUTATION_NAME, - SOCKET_NAME + QUERY_NAME, + MUTATION_NAME, + SOCKET_NAME, + SOCKET_AUTH_NAME ] // for calling the mutation export const PAYLOAD_PARAM_NAME = 'payload' // @TODO shortern them @@ -53,8 +62,8 @@ export const RESOLVER_PARAM_NAME = 'resolverName' export const QUERY_ARG_NAME = 'args' export const TIMESTAMP_PARAM_NAME = 'TS' export const MUTATION_ARGS = [ - RESOLVER_PARAM_NAME, - PAYLOAD_PARAM_NAME, + RESOLVER_PARAM_NAME, + PAYLOAD_PARAM_NAME, CONDITION_PARAM_NAME ] // new jsonp @@ -71,7 +80,7 @@ export const PRIVATE_KEY = 'private' // author export const AUTH_TYPE = 'auth' -export const AUTH_NAME = AUTH_TYPE // alias +export const AUTH_NAME = AUTH_TYPE // alias export const LOGIN_FN_NAME = 'login' // export const ISSUER_NAME = LOGIN_NAME // legacy issue need to replace them later export const LOGOUT_FN_NAME = 'logout' @@ -103,7 +112,7 @@ export const CJS_TYPE = 'cjs' export const ES_TYPE = 'es' export const TS_TYPE = 'ts' export const ACCEPTED_JS_TYPES = [ - CJS_TYPE, + CJS_TYPE, ES_TYPE ] // not accept this TS_TYPE at the moment @@ -111,7 +120,7 @@ export const ACCEPTED_JS_TYPES = [ export const RETURN_AS_FILE = 'file' export const RETURN_AS_JSON = 'json' export const RETURN_AS_ENUM = [ - RETURN_AS_FILE, + RETURN_AS_FILE, RETURN_AS_JSON ] @@ -123,7 +132,7 @@ export const SUCCESS_STATUS = 200 export const UNAUTHORIZED_STATUS = 401 export const FORBIDDEN_STATUS = 403 export const NOT_FOUND_STATUS = 404 -export const NOT_ACCEPTABLE_STATUS = 406 +export const NOT_ACCEPTABLE_STATUS = 406 export const SERVER_INTERNAL_STATUS = 500 // just whatever export const DEFAULT_PORT_NUM = 6557 @@ -236,7 +245,7 @@ export const ENABLE_SPLIT_TASK_PROP_KEY = 'enableSplitTask' /* socket.js */ // the constants file is gettig too large -// we need to split up and group the related constant in one file +// we need to split up and group the related constant in one file // also it makes the other module easiler to id what they are importing // use throughout the clients export const SOCKET_PING_EVENT_NAME = '__ping__' // when init connection do a ping @@ -260,8 +269,8 @@ export const SOCKET_CLIENT_TS_KEY = '__socket_client_ts_key__' // disconnect from the current server, then re-establish connection later export const CONNECTED_EVENT_NAME = '__connected__' export const DISCONNECT_EVENT_NAME = '__disconnect__' -// instead of using an event name in place of resolverName in the param -// we use this internal resolverName instead, and in type using the event names +// instead of using an event name in place of resolverName in the param +// we use this internal resolverName instead, and in type using the event names export const INTERCOM_RESOLVER_NAME = '__intercom__' // group the inter communcation event name in one then for the server // to create a handler to handle this kind of event @@ -276,8 +285,8 @@ export const WS_REPLY_TYPE = '__reply__' export const WS_EVT_NAME = '__event__' export const WS_DATA_NAME = '__data__' export const WS_IS_REPLY_KEYS = [ - WS_REPLY_TYPE, - WS_EVT_NAME, + WS_REPLY_TYPE, + WS_EVT_NAME, WS_DATA_NAME ] @@ -298,8 +307,7 @@ export const USERDATA_PROP_NAME = 'userdata' export const EMIT_REPLY_TYPE = 'emit_reply' export const ACKNOWLEDGE_REPLY_TYPE = 'acknowledge_reply' - -export const NSP_GROUP = 'nspGroup' +export const NSP_GROUP = 'nspGroup' export const PUBLIC_NAMESPACE = 'publicNamespace' export const JS_WS_SOCKET_IO_NAME = 'socket.io' @@ -319,13 +327,13 @@ export const BASE64_FORMAT = 'base64' export const HEX_FORMAT = 'hex' export const UTF8_FORMAT = 'utf8' export const RSA_FORMATS = [ - BASE64_FORMAT, + BASE64_FORMAT, HEX_FORMAT ] export const RSA_ALGO = 'RS256' export const HSA_ALGO = 'HS256' export const JWT_SUPPORT_ALGOS = [ - RSA_ALGO, + RSA_ALGO, HSA_ALGO ] export const RSA_PRIVATE_KEY_HEADER = 'BEGIN RSA PRIVATE KEY' @@ -335,7 +343,7 @@ export const TOKEN_PARAM_NAME = 'token' export const IO_ROUNDTRIP_LOGIN = 'roundtip' export const IO_HANDSHAKE_LOGIN = 'handshake' export const IO_LOGIN_METHODS = [ - IO_ROUNDTRIP_LOGIN, + IO_ROUNDTRIP_LOGIN, IO_HANDSHAKE_LOGIN ] @@ -346,7 +354,7 @@ export const PRIVATE_KEY_NAME = 'privateKey' export const DEFAULT_PUBLIC_KEY_FILE = [PUBLIC_KEY_NAME, PEM_EXT].join('.') export const DEFAULT_PRIVATE_KEY_FILE = [PRIVATE_KEY_NAME, PEM_EXT].join('.') -export const NSP_AUTH_CLIENT = 'nspAuthClient' +export const NSP_AUTH_CLIENT = 'nspAuthClient' export const NSP_CLIENT = 'nspClient' /* validation.js */ diff --git a/packages/constants/main.js b/packages/constants/main.js index 932f0f15..58922d6b 100644 --- a/packages/constants/main.js +++ b/packages/constants/main.js @@ -23,11 +23,17 @@ module.exports = { "QUERY_NAME": "query", "MUTATION_NAME": "mutation", "SOCKET_NAME": "socket", + "SOCKET_AUTH_NAME": "socket-auth", + "EXTERNAL_NAME": "external", + "INTERCEPTOR_NAME": "interceptor", + "PLUGIN_NAME": "plugin", "CONTRACT_NAME": "contract", + "MIDDLEWARE_NAME": "middleware", "RESOLVER_TYPES": [ "query", "mutation", - "socket" + "socket", + "socket-auth" ], "PAYLOAD_PARAM_NAME": "payload", "CONDITION_PARAM_NAME": "condition", diff --git a/packages/constants/package.json b/packages/constants/package.json index c6bb78a1..2942c1b0 100755 --- a/packages/constants/package.json +++ b/packages/constants/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-constants", - "version": "2.0.4", + "version": "2.0.5", "description": "All the share constants for jsonql modules", "main": "main.js", "module": "index.js", diff --git a/packages/constants/socket.js b/packages/constants/socket.js index 58d306d1..24b5356d 100644 --- a/packages/constants/socket.js +++ b/packages/constants/socket.js @@ -1,5 +1,5 @@ // the constants file is gettig too large -// we need to split up and group the related constant in one file +// we need to split up and group the related constant in one file // also it makes the other module easiler to id what they are importing // use throughout the clients export const SOCKET_PING_EVENT_NAME = '__ping__' // when init connection do a ping @@ -23,8 +23,8 @@ export const SOCKET_CLIENT_TS_KEY = '__socket_client_ts_key__' // disconnect from the current server, then re-establish connection later export const CONNECTED_EVENT_NAME = '__connected__' export const DISCONNECT_EVENT_NAME = '__disconnect__' -// instead of using an event name in place of resolverName in the param -// we use this internal resolverName instead, and in type using the event names +// instead of using an event name in place of resolverName in the param +// we use this internal resolverName instead, and in type using the event names export const INTERCOM_RESOLVER_NAME = '__intercom__' // group the inter communcation event name in one then for the server // to create a handler to handle this kind of event @@ -39,8 +39,8 @@ export const WS_REPLY_TYPE = '__reply__' export const WS_EVT_NAME = '__event__' export const WS_DATA_NAME = '__data__' export const WS_IS_REPLY_KEYS = [ - WS_REPLY_TYPE, - WS_EVT_NAME, + WS_REPLY_TYPE, + WS_EVT_NAME, WS_DATA_NAME ] @@ -61,7 +61,7 @@ export const USERDATA_PROP_NAME = 'userdata' export const EMIT_REPLY_TYPE = 'emit_reply' export const ACKNOWLEDGE_REPLY_TYPE = 'acknowledge_reply' -export const NSP_GROUP = 'nspGroup' +export const NSP_GROUP = 'nspGroup' export const PUBLIC_NAMESPACE = 'publicNamespace' export const JS_WS_SOCKET_IO_NAME = 'socket.io' @@ -81,13 +81,13 @@ export const BASE64_FORMAT = 'base64' export const HEX_FORMAT = 'hex' export const UTF8_FORMAT = 'utf8' export const RSA_FORMATS = [ - BASE64_FORMAT, + BASE64_FORMAT, HEX_FORMAT ] export const RSA_ALGO = 'RS256' export const HSA_ALGO = 'HS256' export const JWT_SUPPORT_ALGOS = [ - RSA_ALGO, + RSA_ALGO, HSA_ALGO ] export const RSA_PRIVATE_KEY_HEADER = 'BEGIN RSA PRIVATE KEY' @@ -97,7 +97,7 @@ export const TOKEN_PARAM_NAME = 'token' export const IO_ROUNDTRIP_LOGIN = 'roundtip' export const IO_HANDSHAKE_LOGIN = 'handshake' export const IO_LOGIN_METHODS = [ - IO_ROUNDTRIP_LOGIN, + IO_ROUNDTRIP_LOGIN, IO_HANDSHAKE_LOGIN ] @@ -108,5 +108,5 @@ export const PRIVATE_KEY_NAME = 'privateKey' export const DEFAULT_PUBLIC_KEY_FILE = [PUBLIC_KEY_NAME, PEM_EXT].join('.') export const DEFAULT_PRIVATE_KEY_FILE = [PRIVATE_KEY_NAME, PEM_EXT].join('.') -export const NSP_AUTH_CLIENT = 'nspAuthClient' +export const NSP_AUTH_CLIENT = 'nspAuthClient' export const NSP_CLIENT = 'nspClient' diff --git a/packages/contract-cli/src/generator/get-socket-auth-resolver.js b/packages/contract-cli/src/generator/get-socket-auth-resolver.js index 4943353c..f078ce19 100644 --- a/packages/contract-cli/src/generator/get-socket-auth-resolver.js +++ b/packages/contract-cli/src/generator/get-socket-auth-resolver.js @@ -1,6 +1,6 @@ -// This will be add to the post generate main contract.json file process -// these functions should not appear in the public-contract.json -// its mainly for internal use +// This will be add to the post generate main contract.json file process +// these functions should not appear in the public-contract.json +// its mainly for internal use const fsx = require('fs-extra') const debug = require('debug')('jsonql-contract:generator:get-socket-auth-resolver') const { join, sep, dirname, basename } = require('path') @@ -12,9 +12,9 @@ const { parseFileToAst } = require('./parse-file-to-ast') const { chainPromises } = require('jsonql-utils') /** - * Return the list of files from the folder first - * @param {string} resolverDir where the base resolver directory - * @param {string} [fileExt=EXT] what type of files + * Return the list of files from the folder first + * @param {string} resolverDir where the base resolver directory + * @param {string} [fileExt=EXT] what type of files * @return {promise} resolve the list of files */ function getSocketAuthResolverFiles(resolverDir, fileExt = EXT) { @@ -23,25 +23,25 @@ function getSocketAuthResolverFiles(resolverDir, fileExt = EXT) { return getResolverFiles(dir, fileExt) } debug(`${dir} does not existed!`) - // we don't throw error here just return an empty result + // we don't throw error here just return an empty result return Promise.resolve([]) } /** - * Take the list of files from the folder, then filter out those that are not + * Take the list of files from the folder, then filter out those that are not * registered socket auth files * @param {object} config configuration options * @param {array} authFiles the list of auth files - * @param {string} fileExt the file extension - * @return {object} the list of registered socket auth files using name as key + * @param {string} fileExt the file extension + * @return {object} the list of registered socket auth files using name as key */ function filterAuthFiles(config, authFiles, fileExt = EXT) { - // setup the targets - const { - loginHandlerName, - logoutHandlerName, + // setup the targets + const { + loginHandlerName, + logoutHandlerName, validatorHandlerName, - disconnectHandlerName + disconnectHandlerName } = config const targets = [ loginHandlerName, @@ -53,7 +53,7 @@ function filterAuthFiles(config, authFiles, fileExt = EXT) { return authFiles .map(file => { const name = basename(file).replace('.' + fileExt, '') - // need to take the folder name in if it's an index file + // need to take the folder name in if it's an index file if (name === INDEX_KEY) { const dir = dirname(file).split(sep) @@ -64,21 +64,21 @@ function filterAuthFiles(config, authFiles, fileExt = EXT) { }) .filter(fileObj => { const name = Object.keys(fileObj)[0] - + return inArray(targets, name) }) .reduce((a,b) => Object.assign(a, b), {}) } /** - * This is similiar to the processResolverToContract in get-resolver + * This is similiar to the processResolverToContract in get-resolver * but we don't need that many options, so this is a cut down version * @param {string} file path to the file * @param {string} sourceType what type are they * @return {promise} resolve the partial contract for that particular resolver */ function processFileToContract(name, file, sourceType) { - + return Promise .resolve(fsx.readFileSync(file, 'utf8').toString() ) .then(source => parseFileToAst(source, name, sourceType)) @@ -96,10 +96,10 @@ function processFileToContract(name, file, sourceType) { /** * The main method to generate the partial contract of the socket auth methods - * @param {object} config configuration + * @param {object} config configuration * @param {string|boolean} [sourceType=null] what type of files are they ES6 or CS * @param {string} [fileExt=EXT] the file extension - * @return {promise} resolve the socket auth partial contract + * @return {promise} resolve the socket auth partial contract */ function getSocketAuthResolver(config, sourceType = null, fileExt = EXT) { const { resolverDir } = config @@ -108,9 +108,9 @@ function getSocketAuthResolver(config, sourceType = null, fileExt = EXT) { .then(files => filterAuthFiles(config, files, fileExt)) .then(fileObj => { if (sourceType === null) { - // need to match the expected object structure + // need to match the expected object structure const _files = Object.values(fileObj).map(f => ({file: f})) - + return { sourceType: getSourceType(_files), fileObj @@ -137,21 +137,21 @@ function getSocketAuthResolver(config, sourceType = null, fileExt = EXT) { } /** - * This will be the main interface that insert into the generateOutput + * This will be the main interface that insert into the generateOutput * @param {object} config configuration * @param {object} contract the already working contract - * @return {object} contract with the extra bit + * @return {object} contract with the extra bit */ function processSocketAuth(config, contract) { if (config[SOCKET_NAME] && config.enableAuth === true) { - const { sourceType } = contract + const { sourceType } = contract return getSocketAuthResolver(config, sourceType) .then(partialContract => ( merge({}, contract, partialContract) )) } - return contract + return contract } @@ -162,4 +162,3 @@ module.exports = { getSocketAuthResolverFiles, processSocketAuth } - diff --git a/packages/contract-cli/tests/generator.test.js b/packages/contract-cli/tests/generator.test.js index dfc132d0..10b7b034 100755 --- a/packages/contract-cli/tests/generator.test.js +++ b/packages/contract-cli/tests/generator.test.js @@ -27,8 +27,8 @@ const esResolverDir = join(__dirname, 'fixtures', 'es') const expired = Date.now() + 60*365*1000 test.after(async t => { - // fsx.removeSync(contractDir) - // fsx.removeSync(esContractDir) + fsx.removeSync(contractDir) + fsx.removeSync(esContractDir) // remove the two generate files // @NOTE remove these two files in 1.7.21 // fsx.removeSync( join(esResolverDir, DEFAULT_RESOLVER_LIST_FILE_NAME) ) @@ -51,13 +51,10 @@ test.serial('There should be a contract.json output to the contractDir', async t contractDir, enableAuth: true }) - + debug(result) t.truthy( fsx.existsSync( baseContractFile )) - - - }) // serial. test.only('Should able to create a public-contract.json', async t => { diff --git a/packages/contract-cli/tests/socket.test.js b/packages/contract-cli/tests/socket.test.js index 4f68c0a8..71f6c841 100644 --- a/packages/contract-cli/tests/socket.test.js +++ b/packages/contract-cli/tests/socket.test.js @@ -2,8 +2,15 @@ const test = require('ava') const { join } = require('path') const fsx = require('fs-extra') -const { SOCKET_NAME, AUTH_TYPE } = require('jsonql-constants') -const resolverDir = join(__dirname, 'fixtures', 'resolvers') +const { + SOCKET_NAME, + AUTH_TYPE, + RETURN_AS_JSON, + DEFAULT_CONTRACT_FILE_NAME, + PUBLIC_CONTRACT_FILE_NAME +} = require('jsonql-constants') + +const generator = require('../index') const { filterAuthFiles, getSocketAuthResolverFiles @@ -11,6 +18,12 @@ const { const { getSocketAuthResolver } = require('../extra') const getConfig = require('./fixtures/socket/config') +const resolverDir = join(__dirname, 'fixtures', 'resolvers') +const contractDir = join(__dirname, 'fixtures', 'tmp', 'socket-with-auth') +const baseContractFile = join(contractDir, DEFAULT_CONTRACT_FILE_NAME) +const publicContractFile = join(contractDir, PUBLIC_CONTRACT_FILE_NAME) + + // const socketConfig = require('./fixtures/socket/config') const debug = require('debug')('jsonql-contract:test:socket') @@ -19,6 +32,10 @@ test.before(async t => { }) +test.after(t => { + // fsx.removeSync(contractDir) +}) + test.cb(`It should able to return a list of socket auth files`, t => { t.plan(1) @@ -26,7 +43,7 @@ test.cb(`It should able to return a list of socket auth files`, t => { getSocketAuthResolverFiles(resolverDir) .then(files => { - + debug('files', files) t.truthy(files.length) @@ -44,9 +61,9 @@ test.cb(`It should able to generate partial contract for socket auth`, t => { getSocketAuthResolver(t.context.config) .then(contract => { - + debug('partial contract', contract) - + t.truthy(contract) t.end() }) @@ -54,4 +71,17 @@ test.cb(`It should able to generate partial contract for socket auth`, t => { }) -test.todo(`It should able to generate new entry when socket / auth has content`) +test.cb.only(`It should able to generate new entry when socket / auth has content`, t => { + t.plan(1) + generator({ + resolverDir, + contractDir, + enableAuth: true, + returnAs: RETURN_AS_JSON + }) + .then(result => { + t.truthy(result) + debug('socket test output', result) + t.end() + }) +}) -- Gitee