From a1151cad1757a75fb8f653788e31da51172dac25 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 12:59:00 +0800 Subject: [PATCH 01/26] reorganize all the internal code to use the new koa export --- packages/@jsonql/koa/package.json | 2 +- packages/@jsonql/koa/src/get-socket-server.js | 2 +- packages/@jsonql/koa/src/init-server.js | 7 ++- packages/@jsonql/koa/src/jsonql-koa-server.js | 2 +- packages/@jsonql/koa/src/options/index.js | 62 +++++++++++++++++-- packages/@jsonql/koa/src/options/options.js | 2 +- 6 files changed, 64 insertions(+), 13 deletions(-) diff --git a/packages/@jsonql/koa/package.json b/packages/@jsonql/koa/package.json index ae0892d5..0e63d4ca 100644 --- a/packages/@jsonql/koa/package.json +++ b/packages/@jsonql/koa/package.json @@ -63,7 +63,7 @@ "debug": "^4.1.1", "fs-extra": "^8.1.0", "jsonql-constants": "^1.8.14", - "jsonql-koa": "^1.6.1", + "jsonql-koa": "^1.6.2", "jsonql-params-validator": "^1.5.2", "jsonql-utils": "^0.9.7", "koa": "^2.11.0", diff --git a/packages/@jsonql/koa/src/get-socket-server.js b/packages/@jsonql/koa/src/get-socket-server.js index f7dc0acc..473774f1 100644 --- a/packages/@jsonql/koa/src/get-socket-server.js +++ b/packages/@jsonql/koa/src/get-socket-server.js @@ -6,7 +6,7 @@ const { JS_WS_NAME, JS_WS_SOCKET_IO_NAME, JS_PRIMUS_NAME } = require('jsonql-con * @return {*} false when not found or throw Error when module not found */ function getSocketServer(config, server) { - let wsServer; + let wsServer if (config.serverType) { switch (config.serverType) { case JS_WS_NAME: diff --git a/packages/@jsonql/koa/src/init-server.js b/packages/@jsonql/koa/src/init-server.js index c71e77b6..8407a6f8 100644 --- a/packages/@jsonql/koa/src/init-server.js +++ b/packages/@jsonql/koa/src/init-server.js @@ -3,13 +3,14 @@ const http = require('http') const Koa = require('koa') const bodyparser = require('koa-bodyparser') const cors = require('koa-cors') -// const { jsonqlKoa } = require('../../../koa/main') -const { jsonqlKoa } = require('jsonql-koa') +// const { composeJsonqlKoa } = require('../../../koa/main') +const { composeJsonqlKoa } = require('jsonql-koa') // const { chainFns } = require('jsonql-utils') const { getSocketServer } = require('./get-socket-server') const debug = require('debug')('jsonql-koa:init-server') /** + * Creating all the required servers * @param {object} config configuration * @param {array} middlewares what it said * @return {object} see below for detail @@ -23,7 +24,7 @@ function initServer(config, middlewares) { app.use(cors()) } // init jsonqlKoa - app.use(jsonqlKoa(config)) + app.use(composeJsonqlKoa(config)) // if any middlewares.forEach(middleware => { app.use(middleware) diff --git a/packages/@jsonql/koa/src/jsonql-koa-server.js b/packages/@jsonql/koa/src/jsonql-koa-server.js index 25b054f6..f1ffeacc 100644 --- a/packages/@jsonql/koa/src/jsonql-koa-server.js +++ b/packages/@jsonql/koa/src/jsonql-koa-server.js @@ -1,6 +1,6 @@ // main const debug = require('debug')('jsonql-koa:jsonql-koa-server') -const checkOptions = require('./options') +const { checkOptions } = require('./options') const { initServer } = require('./init-server') const { version } = require('../package.json') diff --git a/packages/@jsonql/koa/src/options/index.js b/packages/@jsonql/koa/src/options/index.js index 7906201e..695e2cfe 100644 --- a/packages/@jsonql/koa/src/options/index.js +++ b/packages/@jsonql/koa/src/options/index.js @@ -1,20 +1,70 @@ // check options -const { options } = require('./options') -const { preConfigCheck } = require('jsonql-koa') +const { jsonqlKoaOptions } = require('./options') +const { extendConfigCheck } = require('jsonql-koa') // @TODO there will be the socket.io version or primus in the future // therefore the merge options should be conditional +const { JS_WS_NAME, JS_WS_SOCKET_IO_NAME, JS_PRIMUS_NAME } = require('jsonql-constants') +const { inArray } = require('jsonql-utils') +// how to make this an optional module? const { wsServerDefaultOptions, wsServerConstProps } = require('jsonql-ws-server') +const extendOptions = { + nil: { + appProps: {}, + constProps: {} + }, + [JS_WS_NAME]: { + appProps: wsServerDefaultOptions, + constProps: wsServerConstProps + }, + [JS_WS_SOCKET_IO_NAME]: { + appProps: {}, + constProps: {} + }, + [JS_PRIMUS_NAME]: { + appProps: {}, + constProps: {} + } +} + +const availableServers = [ + JS_WS_NAME + // JS_WS_SOCKET_IO_NAME + // JS_PRIMUS_NAME add this in the future +] + +/** + * Just check the server type before we run the configuration + * @param {object} config options + * @return {object} the serverType + options or empty objects when there is no serverType field + */ +function getServerType(config) { + const { serverType } = config + if (serverType) { + if (inArray(availableServers, serverType)) { + return extendOptions[serverType] + } + } + return extendOptions.nil +} /** * the default api to check and init the config * @param {object} config user supply configuration * @return {object} configuration */ -module.exports = function checkOptions(config) { +function checkOptions(config) { + // @TODO here is a catch 22, if we take the serverType out, then we double check it again ... + const { appProps, constProps } = getServerType(config) + // first create a combine options - return preConfigCheck( - Object.assign(wsServerDefaultOptions, options), - wsServerConstProps, + return extendConfigCheck( + Object.assign({}, jsonqlKoaOptions, appProps), + constProps, config ) } + +module.exports = { + checkOptions, + getServerType +} diff --git a/packages/@jsonql/koa/src/options/options.js b/packages/@jsonql/koa/src/options/options.js index 636aba94..e79a18a8 100644 --- a/packages/@jsonql/koa/src/options/options.js +++ b/packages/@jsonql/koa/src/options/options.js @@ -23,5 +23,5 @@ const options = { } module.exports = { - options + jsonqlKoaOptions: options } -- Gitee From bb32a2b8769e21426a861928c99475d7e72d4318 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 13:10:31 +0800 Subject: [PATCH 02/26] need to change how the ws server init before we continue here --- packages/@jsonql/koa/package.json | 2 +- packages/@jsonql/koa/src/get-socket-server.js | 2 + packages/@jsonql/koa/tests/auth.test.js | 5 +- packages/@jsonql/koa/tests/basic.test.js | 4 +- .../contract/client1/public-contract.json | 279 ------------- .../contract/client2/public-contract.json | 58 --- .../ms-a/client0/public-contract.json | 58 --- .../ms-a/client2c/public-contract.json | 58 --- .../fixtures/contract/ms-a/contract.json | 319 --------------- .../contract/ms-a/public-contract.json | 293 -------------- .../fixtures/contract/ms-b/contract.json | 56 --- .../contract/ms-b/public-contract.json | 62 --- .../fixtures/contract/ms-c/contract.json | 56 --- .../contract/ms-c/public-contract.json | 62 --- .../fixtures/contract/socket/contract.json | 367 ------------------ .../contract/socket/public-contract.json | 360 ----------------- packages/@jsonql/koa/tests/ms.test.js | 2 +- packages/@jsonql/koa/tests/socket.test.js | 2 - 18 files changed, 9 insertions(+), 2036 deletions(-) delete mode 100644 packages/@jsonql/koa/tests/fixtures/contract/client1/public-contract.json delete mode 100644 packages/@jsonql/koa/tests/fixtures/contract/client2/public-contract.json delete mode 100644 packages/@jsonql/koa/tests/fixtures/contract/ms-a/client0/public-contract.json delete mode 100644 packages/@jsonql/koa/tests/fixtures/contract/ms-a/client2c/public-contract.json delete mode 100644 packages/@jsonql/koa/tests/fixtures/contract/ms-a/contract.json delete mode 100644 packages/@jsonql/koa/tests/fixtures/contract/ms-a/public-contract.json delete mode 100644 packages/@jsonql/koa/tests/fixtures/contract/ms-b/contract.json delete mode 100644 packages/@jsonql/koa/tests/fixtures/contract/ms-b/public-contract.json delete mode 100644 packages/@jsonql/koa/tests/fixtures/contract/ms-c/contract.json delete mode 100644 packages/@jsonql/koa/tests/fixtures/contract/ms-c/public-contract.json delete mode 100644 packages/@jsonql/koa/tests/fixtures/contract/socket/contract.json delete mode 100644 packages/@jsonql/koa/tests/fixtures/contract/socket/public-contract.json diff --git a/packages/@jsonql/koa/package.json b/packages/@jsonql/koa/package.json index 0e63d4ca..ed028644 100644 --- a/packages/@jsonql/koa/package.json +++ b/packages/@jsonql/koa/package.json @@ -1,6 +1,6 @@ { "name": "@jsonql/koa", - "version": "0.9.1", + "version": "0.9.2", "description": "This is the all in one package to start your jsonql project with Koa, jsonql-koa, jsonql-ws-server and more", "main": "index.js", "files": [ diff --git a/packages/@jsonql/koa/src/get-socket-server.js b/packages/@jsonql/koa/src/get-socket-server.js index 473774f1..e820f3bc 100644 --- a/packages/@jsonql/koa/src/get-socket-server.js +++ b/packages/@jsonql/koa/src/get-socket-server.js @@ -20,6 +20,8 @@ function getSocketServer(config, server) { console.error(`Not support ${config.serverType} at the moment!`) return false } + // there is a problem with the socket-server that need to fix first + return wsServer(config, server) } return false diff --git a/packages/@jsonql/koa/tests/auth.test.js b/packages/@jsonql/koa/tests/auth.test.js index 0970d813..4c85cc81 100644 --- a/packages/@jsonql/koa/tests/auth.test.js +++ b/packages/@jsonql/koa/tests/auth.test.js @@ -3,11 +3,11 @@ const fsx = require('fs-extra') const { join } = require('path') const debug = require('debug')('jsonql-koa:test:auth') const jsonqlNodeClient = require('jsonql-node-client') -const { JS_WS_NAME, HELLO } = require('jsonql-constants') +const { HELLO } = require('jsonql-constants') const jsonqlKoaServer = require('./fixtures/test-server') const { contractBaseDir, AUTH_DIR } = require('./fixtures/options') const contractDir = join(contractBaseDir, AUTH_DIR) -const port = 8082; +const port = 8082 test.before(t => { const jsonqlKoaInt = jsonqlKoaServer({ @@ -52,6 +52,7 @@ test.serial.cb(`It should able to login`, t => { const name = 'Joel' client.login(name) .then(result => { + debug('login result', result) const userdata = client.userdata() t.is(userdata.name, name) diff --git a/packages/@jsonql/koa/tests/basic.test.js b/packages/@jsonql/koa/tests/basic.test.js index 5f1391ce..8a4d01d7 100644 --- a/packages/@jsonql/koa/tests/basic.test.js +++ b/packages/@jsonql/koa/tests/basic.test.js @@ -3,8 +3,8 @@ const test = require('ava') const fsx = require('fs-extra') const { join } = require('path') const jsonqlNodeClient = require('jsonql-node-client') -const debug = require('debug')('jsonql-koa:test:basic') -const { JS_WS_NAME, HELLO } = require('jsonql-constants') +// const debug = require('debug')('jsonql-koa:test:basic') +const { HELLO } = require('jsonql-constants') const { contractBaseDir, BASIC_DIR } = require('./fixtures/options') const contractDir = join(contractBaseDir, BASIC_DIR) diff --git a/packages/@jsonql/koa/tests/fixtures/contract/client1/public-contract.json b/packages/@jsonql/koa/tests/fixtures/contract/client1/public-contract.json deleted file mode 100644 index c443b2a7..00000000 --- a/packages/@jsonql/koa/tests/fixtures/contract/client1/public-contract.json +++ /dev/null @@ -1,279 +0,0 @@ -{ - "query": { - "helloWorld": { - "params": [], - "returns": [ - { - "type": "string", - "description": "stock message" - } - ] - }, - "causeError": { - "params": [ - { - "type": [ - "any" - ], - "name": "x", - "description": "param" - } - ], - "returns": [ - { - "type": [ - "any" - ], - "description": "unknown" - } - ] - }, - "getSomething": { - "params": [], - "returns": [ - { - "type": [ - "object" - ], - "description": "an object contains two different time stamps" - } - ] - }, - "getUser": { - "params": [ - { - "type": [ - "string" - ], - "name": "args", - "variable": true, - "description": "passing unknown number of param" - } - ], - "returns": [ - { - "type": [ - "any" - ], - "description": "extract from last of the args" - } - ] - }, - "alwaysAvailable": { - "public": true, - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message" - } - ] - }, - "testList": { - "params": [ - { - "type": [ - "number" - ], - "name": "num", - "description": "a number" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "@TODO need to figure out how to give keys to the returns" - } - ] - } - }, - "mutation": { - "saveRemote": { - "params": [ - { - "type": [ - "object" - ], - "name": "payload", - "description": "something to save" - }, - { - "type": [ - "number" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "with array of timestamp" - } - ] - }, - "updateList": { - "params": [ - { - "type": [ - "object" - ], - "name": "payload", - "keys": [ - { - "type": [ - "number" - ], - "name": "user", - "parent": "payload" - } - ] - }, - { - "type": [ - "object" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "with user as key" - } - ] - } - }, - "auth": {}, - "timestamp": 1583151676, - "socket": { - "causeError": { - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "a message" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message but here we throw an error" - } - ] - }, - "chatroom": { - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "for checking the time" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "reply" - } - ] - }, - "delayFn": { - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "a message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "a timestamp" - } - ], - "returns": false - }, - "msPass": { - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "an incoming message" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "contain everything and send it back" - } - ] - }, - "availableToEveryone": { - "public": true, - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message" - } - ] - }, - "wsHandler": { - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "timestamp" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "msg + time lapsed" - } - ] - } - } -} diff --git a/packages/@jsonql/koa/tests/fixtures/contract/client2/public-contract.json b/packages/@jsonql/koa/tests/fixtures/contract/client2/public-contract.json deleted file mode 100644 index 2d6ecbfd..00000000 --- a/packages/@jsonql/koa/tests/fixtures/contract/client2/public-contract.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "query": { - "helloWorld": { - "params": [], - "returns": [ - { - "type": "string", - "description": "stock message" - } - ] - }, - "sendingOutSomething": { - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a random message" - } - ] - } - }, - "mutation": { - "saveSomething": { - "params": [ - { - "type": [ - "object" - ], - "name": "payload" - }, - { - "type": [ - "number" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "result" - } - ] - } - }, - "auth": {}, - "timestamp": 1583151676, - "socket": { - "giveNumber": { - "params": [], - "returns": false - } - } -} diff --git a/packages/@jsonql/koa/tests/fixtures/contract/ms-a/client0/public-contract.json b/packages/@jsonql/koa/tests/fixtures/contract/ms-a/client0/public-contract.json deleted file mode 100644 index 2d6ecbfd..00000000 --- a/packages/@jsonql/koa/tests/fixtures/contract/ms-a/client0/public-contract.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "query": { - "helloWorld": { - "params": [], - "returns": [ - { - "type": "string", - "description": "stock message" - } - ] - }, - "sendingOutSomething": { - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a random message" - } - ] - } - }, - "mutation": { - "saveSomething": { - "params": [ - { - "type": [ - "object" - ], - "name": "payload" - }, - { - "type": [ - "number" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "result" - } - ] - } - }, - "auth": {}, - "timestamp": 1583151676, - "socket": { - "giveNumber": { - "params": [], - "returns": false - } - } -} diff --git a/packages/@jsonql/koa/tests/fixtures/contract/ms-a/client2c/public-contract.json b/packages/@jsonql/koa/tests/fixtures/contract/ms-a/client2c/public-contract.json deleted file mode 100644 index 2d6ecbfd..00000000 --- a/packages/@jsonql/koa/tests/fixtures/contract/ms-a/client2c/public-contract.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "query": { - "helloWorld": { - "params": [], - "returns": [ - { - "type": "string", - "description": "stock message" - } - ] - }, - "sendingOutSomething": { - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a random message" - } - ] - } - }, - "mutation": { - "saveSomething": { - "params": [ - { - "type": [ - "object" - ], - "name": "payload" - }, - { - "type": [ - "number" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "result" - } - ] - } - }, - "auth": {}, - "timestamp": 1583151676, - "socket": { - "giveNumber": { - "params": [], - "returns": false - } - } -} diff --git a/packages/@jsonql/koa/tests/fixtures/contract/ms-a/contract.json b/packages/@jsonql/koa/tests/fixtures/contract/ms-a/contract.json deleted file mode 100644 index 67748816..00000000 --- a/packages/@jsonql/koa/tests/fixtures/contract/ms-a/contract.json +++ /dev/null @@ -1,319 +0,0 @@ -{ - "query": { - "causeError": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/query/cause-error.js", - "description": false, - "params": [ - { - "type": [ - "any" - ], - "name": "x", - "description": "param" - } - ], - "returns": [ - { - "type": [ - "any" - ], - "description": "unknown" - } - ] - }, - "getSomething": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/query/get-something.js", - "description": "just a pass over method to get something from server b", - "params": [], - "returns": [ - { - "type": [ - "object" - ], - "description": "an object contains two different time stamps" - } - ] - }, - "getUser": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/query/get-user.js", - "description": "This use a spread as parameter", - "params": [ - { - "type": [ - "string" - ], - "name": "args", - "variable": true, - "description": "passing unknown number of param" - } - ], - "returns": [ - { - "type": [ - "any" - ], - "description": "extract from last of the args" - } - ] - }, - "alwaysAvailable": { - "public": true, - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/query/public/always-available.js", - "description": "This is a public method that is always available", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message" - } - ] - }, - "testList": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/query/test-list.js", - "description": false, - "params": [ - { - "type": [ - "number" - ], - "name": "num", - "description": "a number" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "@TODO need to figure out how to give keys to the returns" - } - ] - } - }, - "mutation": { - "saveRemote": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/mutation/save-remote.js", - "description": "This will call the remote ms to save the result then modified it", - "params": [ - { - "type": [ - "object" - ], - "name": "payload", - "description": "something to save" - }, - { - "type": [ - "number" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "with array of timestamp" - } - ] - }, - "updateList": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/mutation/update-list.js", - "description": false, - "params": [ - { - "type": [ - "object" - ], - "name": "payload", - "keys": [ - { - "type": [ - "number" - ], - "name": "user", - "parent": "payload" - } - ] - }, - { - "type": [ - "object" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "with user as key" - } - ] - } - }, - "auth": { - "login": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/auth/login.js", - "description": "login method", - "params": [ - { - "type": [ - "string" - ], - "name": "name", - "description": "give it a name" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "a userdata object with timestamp" - } - ] - } - }, - "timestamp": 1583151675, - "sourceType": "script", - "socket": { - "causeError": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/socket/cause-error.js", - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "a message" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message but here we throw an error" - } - ] - }, - "chatroom": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/socket/chatroom.js", - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "for checking the time" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "reply" - } - ] - }, - "delayFn": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/socket/delay-fn.js", - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "a message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "a timestamp" - } - ], - "returns": false - }, - "msPass": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/socket/ms-pass.js", - "description": "just a pass over method to call server B", - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "an incoming message" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "contain everything and send it back" - } - ] - }, - "availableToEveryone": { - "public": true, - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/socket/public/available-to-everyone/index.js", - "description": "There is no parameter require for this call", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message" - } - ] - }, - "wsHandler": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/socket/ws-handler.js", - "description": "method just for testing the ws", - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "timestamp" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "msg + time lapsed" - } - ] - } - } -} diff --git a/packages/@jsonql/koa/tests/fixtures/contract/ms-a/public-contract.json b/packages/@jsonql/koa/tests/fixtures/contract/ms-a/public-contract.json deleted file mode 100644 index 61ec2cfa..00000000 --- a/packages/@jsonql/koa/tests/fixtures/contract/ms-a/public-contract.json +++ /dev/null @@ -1,293 +0,0 @@ -{ - "query": { - "helloWorld": { - "description": "This is the stock resolver for testing purpose", - "params": [], - "returns": [ - { - "type": "string", - "description": "stock message" - } - ] - }, - "causeError": { - "description": false, - "params": [ - { - "type": [ - "any" - ], - "name": "x", - "description": "param" - } - ], - "returns": [ - { - "type": [ - "any" - ], - "description": "unknown" - } - ] - }, - "getSomething": { - "description": "just a pass over method to get something from server b", - "params": [], - "returns": [ - { - "type": [ - "object" - ], - "description": "an object contains two different time stamps" - } - ] - }, - "getUser": { - "description": "This use a spread as parameter", - "params": [ - { - "type": [ - "string" - ], - "name": "args", - "variable": true, - "description": "passing unknown number of param" - } - ], - "returns": [ - { - "type": [ - "any" - ], - "description": "extract from last of the args" - } - ] - }, - "alwaysAvailable": { - "public": true, - "description": "This is a public method that is always available", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message" - } - ] - }, - "testList": { - "description": false, - "params": [ - { - "type": [ - "number" - ], - "name": "num", - "description": "a number" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "@TODO need to figure out how to give keys to the returns" - } - ] - } - }, - "mutation": { - "saveRemote": { - "description": "This will call the remote ms to save the result then modified it", - "params": [ - { - "type": [ - "object" - ], - "name": "payload", - "description": "something to save" - }, - { - "type": [ - "number" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "with array of timestamp" - } - ] - }, - "updateList": { - "description": false, - "params": [ - { - "type": [ - "object" - ], - "name": "payload", - "keys": [ - { - "type": [ - "number" - ], - "name": "user", - "parent": "payload" - } - ] - }, - { - "type": [ - "object" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "with user as key" - } - ] - } - }, - "auth": {}, - "timestamp": 1583151676, - "socket": { - "causeError": { - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "a message" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message but here we throw an error" - } - ] - }, - "chatroom": { - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "for checking the time" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "reply" - } - ] - }, - "delayFn": { - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "a message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "a timestamp" - } - ], - "returns": false - }, - "msPass": { - "description": "just a pass over method to call server B", - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "an incoming message" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "contain everything and send it back" - } - ] - }, - "availableToEveryone": { - "public": true, - "description": "There is no parameter require for this call", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message" - } - ] - }, - "wsHandler": { - "description": "method just for testing the ws", - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "timestamp" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "msg + time lapsed" - } - ] - } - } -} diff --git a/packages/@jsonql/koa/tests/fixtures/contract/ms-b/contract.json b/packages/@jsonql/koa/tests/fixtures/contract/ms-b/contract.json deleted file mode 100644 index 021e16a7..00000000 --- a/packages/@jsonql/koa/tests/fixtures/contract/ms-b/contract.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "query": { - "sendingOutSomething": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers-ext/query/sending-out-something.js", - "description": "This is publicly available server whenever connect just send out a random message", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a random message" - } - ] - } - }, - "mutation": { - "saveSomething": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers-ext/mutation/save-something.js", - "description": "this is for a remote C server to call", - "params": [ - { - "type": [ - "object" - ], - "name": "payload" - }, - { - "type": [ - "number" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "result" - } - ] - } - }, - "auth": {}, - "timestamp": 1583151676, - "sourceType": "script", - "socket": { - "giveNumber": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers-ext/socket/give-number.js", - "description": "This is the socket interface that is publicly available and whenever connect\nwill give you a timestamp", - "params": [], - "returns": false - } - } -} diff --git a/packages/@jsonql/koa/tests/fixtures/contract/ms-b/public-contract.json b/packages/@jsonql/koa/tests/fixtures/contract/ms-b/public-contract.json deleted file mode 100644 index 73ec4afd..00000000 --- a/packages/@jsonql/koa/tests/fixtures/contract/ms-b/public-contract.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "query": { - "helloWorld": { - "description": "This is the stock resolver for testing purpose", - "params": [], - "returns": [ - { - "type": "string", - "description": "stock message" - } - ] - }, - "sendingOutSomething": { - "description": "This is publicly available server whenever connect just send out a random message", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a random message" - } - ] - } - }, - "mutation": { - "saveSomething": { - "description": "this is for a remote C server to call", - "params": [ - { - "type": [ - "object" - ], - "name": "payload" - }, - { - "type": [ - "number" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "result" - } - ] - } - }, - "auth": {}, - "timestamp": 1583151676, - "socket": { - "giveNumber": { - "description": "This is the socket interface that is publicly available and whenever connect\nwill give you a timestamp", - "params": [], - "returns": false - } - } -} diff --git a/packages/@jsonql/koa/tests/fixtures/contract/ms-c/contract.json b/packages/@jsonql/koa/tests/fixtures/contract/ms-c/contract.json deleted file mode 100644 index 7c1013bf..00000000 --- a/packages/@jsonql/koa/tests/fixtures/contract/ms-c/contract.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "query": { - "sendingOutSomething": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers-ext/query/sending-out-something.js", - "description": "This is publicly available server whenever connect just send out a random message", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a random message" - } - ] - } - }, - "mutation": { - "saveSomething": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers-ext/mutation/save-something.js", - "description": "this is for a remote C server to call", - "params": [ - { - "type": [ - "object" - ], - "name": "payload" - }, - { - "type": [ - "number" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "result" - } - ] - } - }, - "auth": {}, - "timestamp": 1583151675, - "sourceType": "script", - "socket": { - "giveNumber": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers-ext/socket/give-number.js", - "description": "This is the socket interface that is publicly available and whenever connect\nwill give you a timestamp", - "params": [], - "returns": false - } - } -} diff --git a/packages/@jsonql/koa/tests/fixtures/contract/ms-c/public-contract.json b/packages/@jsonql/koa/tests/fixtures/contract/ms-c/public-contract.json deleted file mode 100644 index 73ec4afd..00000000 --- a/packages/@jsonql/koa/tests/fixtures/contract/ms-c/public-contract.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "query": { - "helloWorld": { - "description": "This is the stock resolver for testing purpose", - "params": [], - "returns": [ - { - "type": "string", - "description": "stock message" - } - ] - }, - "sendingOutSomething": { - "description": "This is publicly available server whenever connect just send out a random message", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a random message" - } - ] - } - }, - "mutation": { - "saveSomething": { - "description": "this is for a remote C server to call", - "params": [ - { - "type": [ - "object" - ], - "name": "payload" - }, - { - "type": [ - "number" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "result" - } - ] - } - }, - "auth": {}, - "timestamp": 1583151676, - "socket": { - "giveNumber": { - "description": "This is the socket interface that is publicly available and whenever connect\nwill give you a timestamp", - "params": [], - "returns": false - } - } -} diff --git a/packages/@jsonql/koa/tests/fixtures/contract/socket/contract.json b/packages/@jsonql/koa/tests/fixtures/contract/socket/contract.json deleted file mode 100644 index e16526cf..00000000 --- a/packages/@jsonql/koa/tests/fixtures/contract/socket/contract.json +++ /dev/null @@ -1,367 +0,0 @@ -{ - "query": { - "causeError": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/query/cause-error.js", - "description": false, - "params": [ - { - "type": [ - "any" - ], - "name": "x", - "description": "param" - } - ], - "returns": [ - { - "type": [ - "any" - ], - "description": "unknown" - } - ] - }, - "getSomething": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/query/get-something.js", - "description": "just a pass over method to get something from server b", - "params": [], - "returns": [ - { - "type": [ - "object" - ], - "description": "an object contains two different time stamps" - } - ] - }, - "getUser": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/query/get-user.js", - "description": "This use a spread as parameter", - "params": [ - { - "type": [ - "string" - ], - "name": "args", - "variable": true, - "description": "passing unknown number of param" - } - ], - "returns": [ - { - "type": [ - "any" - ], - "description": "extract from last of the args" - } - ] - }, - "getSecretMsg": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/query/private/get-secret-msg.js", - "description": "a hidden private method", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a secret message" - } - ] - }, - "alwaysAvailable": { - "public": true, - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/query/public/always-available.js", - "description": "This is a public method that is always available", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message" - } - ] - }, - "testList": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/query/test-list.js", - "description": false, - "params": [ - { - "type": [ - "number" - ], - "name": "num", - "description": "a number" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "@TODO need to figure out how to give keys to the returns" - } - ] - } - }, - "mutation": { - "saveRemote": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/mutation/save-remote.js", - "description": "This will call the remote ms to save the result then modified it", - "params": [ - { - "type": [ - "object" - ], - "name": "payload", - "description": "something to save" - }, - { - "type": [ - "number" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "with array of timestamp" - } - ] - }, - "updateList": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/mutation/update-list.js", - "description": false, - "params": [ - { - "type": [ - "object" - ], - "name": "payload", - "keys": [ - { - "type": [ - "number" - ], - "name": "user", - "parent": "payload" - } - ] - }, - { - "type": [ - "object" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "with user as key" - } - ] - } - }, - "auth": { - "login": { - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/auth/login.js", - "description": "login method", - "params": [ - { - "type": [ - "string" - ], - "name": "name", - "description": "give it a name" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "a userdata object with timestamp" - } - ] - } - }, - "timestamp": 1583152295, - "sourceType": "script", - "socket": { - "causeError": { - "namespace": "jsonql/private", - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/socket/cause-error.js", - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "a message" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message but here we throw an error" - } - ] - }, - "chatroom": { - "namespace": "jsonql/private", - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/socket/chatroom.js", - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "for checking the time" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "reply" - } - ] - }, - "delayFn": { - "namespace": "jsonql/private", - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/socket/delay-fn.js", - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "a message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "a timestamp" - } - ], - "returns": false - }, - "msPass": { - "namespace": "jsonql/private", - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/socket/ms-pass.js", - "description": "just a pass over method to call server B", - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "an incoming message" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "contain everything and send it back" - } - ] - }, - "secretChatroom": { - "namespace": "jsonql/private", - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/socket/private/secret-chatroom.js", - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "room", - "description": "room name" - }, - { - "type": [ - "any" - ], - "name": "msg", - "description": "message to that room" - } - ], - "returns": [ - { - "type": [ - "any" - ], - "description": "depends" - } - ] - }, - "availableToEveryone": { - "namespace": "jsonql/public", - "public": true, - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/socket/public/available-to-everyone/index.js", - "description": "There is no parameter require for this call", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message" - } - ] - }, - "wsHandler": { - "namespace": "jsonql/private", - "file": "/home/joel/projects/open-source/jsonql/packages/@jsonql/koa/tests/fixtures/resolvers/socket/ws-handler.js", - "description": "method just for testing the ws", - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "timestamp" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "msg + time lapsed" - } - ] - } - } -} diff --git a/packages/@jsonql/koa/tests/fixtures/contract/socket/public-contract.json b/packages/@jsonql/koa/tests/fixtures/contract/socket/public-contract.json deleted file mode 100644 index 8c5665af..00000000 --- a/packages/@jsonql/koa/tests/fixtures/contract/socket/public-contract.json +++ /dev/null @@ -1,360 +0,0 @@ -{ - "query": { - "helloWorld": { - "description": "This is the stock resolver for testing purpose", - "params": [], - "returns": [ - { - "type": "string", - "description": "stock message" - } - ] - }, - "causeError": { - "description": false, - "params": [ - { - "type": [ - "any" - ], - "name": "x", - "description": "param" - } - ], - "returns": [ - { - "type": [ - "any" - ], - "description": "unknown" - } - ] - }, - "getSomething": { - "description": "just a pass over method to get something from server b", - "params": [], - "returns": [ - { - "type": [ - "object" - ], - "description": "an object contains two different time stamps" - } - ] - }, - "getUser": { - "description": "This use a spread as parameter", - "params": [ - { - "type": [ - "string" - ], - "name": "args", - "variable": true, - "description": "passing unknown number of param" - } - ], - "returns": [ - { - "type": [ - "any" - ], - "description": "extract from last of the args" - } - ] - }, - "getSecretMsg": { - "description": "a hidden private method", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a secret message" - } - ] - }, - "alwaysAvailable": { - "public": true, - "description": "This is a public method that is always available", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message" - } - ] - }, - "testList": { - "description": false, - "params": [ - { - "type": [ - "number" - ], - "name": "num", - "description": "a number" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "@TODO need to figure out how to give keys to the returns" - } - ] - } - }, - "mutation": { - "saveRemote": { - "description": "This will call the remote ms to save the result then modified it", - "params": [ - { - "type": [ - "object" - ], - "name": "payload", - "description": "something to save" - }, - { - "type": [ - "number" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "with array of timestamp" - } - ] - }, - "updateList": { - "description": false, - "params": [ - { - "type": [ - "object" - ], - "name": "payload", - "keys": [ - { - "type": [ - "number" - ], - "name": "user", - "parent": "payload" - } - ] - }, - { - "type": [ - "object" - ], - "name": "condition" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "with user as key" - } - ] - } - }, - "auth": { - "login": { - "description": "login method", - "params": [ - { - "type": [ - "string" - ], - "name": "name", - "description": "give it a name" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "a userdata object with timestamp" - } - ] - } - }, - "timestamp": 1583152296, - "socket": { - "causeError": { - "namespace": "jsonql/private", - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "a message" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message but here we throw an error" - } - ] - }, - "chatroom": { - "namespace": "jsonql/private", - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "for checking the time" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "reply" - } - ] - }, - "delayFn": { - "namespace": "jsonql/private", - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "a message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "a timestamp" - } - ], - "returns": false - }, - "msPass": { - "namespace": "jsonql/private", - "description": "just a pass over method to call server B", - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "an incoming message" - } - ], - "returns": [ - { - "type": [ - "object" - ], - "description": "contain everything and send it back" - } - ] - }, - "secretChatroom": { - "namespace": "jsonql/private", - "description": false, - "params": [ - { - "type": [ - "string" - ], - "name": "room", - "description": "room name" - }, - { - "type": [ - "any" - ], - "name": "msg", - "description": "message to that room" - } - ], - "returns": [ - { - "type": [ - "any" - ], - "description": "depends" - } - ] - }, - "availableToEveryone": { - "namespace": "jsonql/public", - "public": true, - "description": "There is no parameter require for this call", - "params": [], - "returns": [ - { - "type": [ - "string" - ], - "description": "a message" - } - ] - }, - "wsHandler": { - "namespace": "jsonql/private", - "description": "method just for testing the ws", - "params": [ - { - "type": [ - "string" - ], - "name": "msg", - "description": "message" - }, - { - "type": [ - "number" - ], - "name": "timestamp", - "description": "timestamp" - } - ], - "returns": [ - { - "type": [ - "string" - ], - "description": "msg + time lapsed" - } - ] - } - } -} diff --git a/packages/@jsonql/koa/tests/ms.test.js b/packages/@jsonql/koa/tests/ms.test.js index 812a2449..da00b44d 100644 --- a/packages/@jsonql/koa/tests/ms.test.js +++ b/packages/@jsonql/koa/tests/ms.test.js @@ -4,7 +4,7 @@ const fsx = require('fs-extra') const { join } = require('path') const jsonqlNodeClient = require('jsonql-node-client') const debug = require('debug')('jsonql-koa:test:basic') -const { JS_WS_NAME, HELLO } = require('jsonql-constants') +const { HELLO } = require('jsonql-constants') const { contractBaseDir, MS_A_DIR, MS_B_DIR, PORT_A, PORT_B } = require('./fixtures/options') const contractDirA = join(contractBaseDir, MS_A_DIR) diff --git a/packages/@jsonql/koa/tests/socket.test.js b/packages/@jsonql/koa/tests/socket.test.js index bce539e6..64a20e81 100644 --- a/packages/@jsonql/koa/tests/socket.test.js +++ b/packages/@jsonql/koa/tests/socket.test.js @@ -73,6 +73,4 @@ test.cb.skip(`It should able to login to the socket and connect to a private soc t.is(user.name, 'Jack') t.end() } - - }) -- Gitee From 4a8c1cd1b764864252d98dc9b4593303440ff926 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 14:59:35 +0800 Subject: [PATCH 03/26] reorganize and clean up the jsonql-ws-server-core internal --- packages/ws-server-core/README.md | 21 ++++- packages/ws-server-core/index.js | 43 ++++++--- packages/ws-server-core/package.json | 28 +++--- packages/ws-server-core/src/options/index.js | 87 ++++++++++--------- .../ws-server-core/src/share/add-property.js | 2 +- .../ws-server-core/src/share/constants.js | 6 +- .../ws-server-core/src/share/get-contract.js | 2 +- packages/ws-server-core/src/share/helpers.js | 17 ++-- .../src/share/resolve-method.js | 24 +++-- 9 files changed, 133 insertions(+), 97 deletions(-) diff --git a/packages/ws-server-core/README.md b/packages/ws-server-core/README.md index 3ba32f84..e3f4397a 100644 --- a/packages/ws-server-core/README.md +++ b/packages/ws-server-core/README.md @@ -1,11 +1,30 @@ # jsonql-ws-server-core -> This is the core module for Jsonql Web Socket server +> This is the core module for Jsonql WS Web Socket server This module is not intend to use directly. Check [jsonql.org](http://jsonql.org) for more information. +## Export modules + +This is for our own reference use **ONLY**: + +- addProperty +- getContract +- createWsReply +- getDebug +- getNamespace +- extractWsPayload +- nil +- getUserdata +- resolveMethod +- wsServerDefaultOptions +- wsServerConstProps +- jsonqlWsCoreConstants +- jsonqlWsServerCore +- jsonqlWsServerCoreAction + --- [NEWBRAN LTD UK](https://newbran.ch) diff --git a/packages/ws-server-core/index.js b/packages/ws-server-core/index.js index 8bec757e..22f90819 100644 --- a/packages/ws-server-core/index.js +++ b/packages/ws-server-core/index.js @@ -2,7 +2,7 @@ // which is completely useless for us if there is no namespace const { JsonqlError } = require('jsonql-errors') const { - checkConfig, + checkWsConfig, wsServerDefaultOptions, wsServerConstProps } = require('./src') @@ -23,6 +23,30 @@ const { resolveMethod } = require('./src/share/resolve-method') const debug = getDebug('main') // also report the constants const jsonqlWsCoreConstants = require('./src/share/constants') + +/** + * @0.4.0 we breaking up the config and init server in two fn + * Then when we need to combine with other modules, we only use the init + * Also there might be a chance that we need to merge the contract? + * @param {object} obj combine several properties in one + * @param {object} obj.opts checked configuration options + * @param {object} obj.server the http server instance + * @param {object} obj.wsCreateServer reverse passing the wsCreateServer fn from outter module + * @param {object} obj.wsSetup a pre start up function pass from outter module + * @return {promise} checked config + */ +function jsonqlWsServerCoreAction({opts, server, wsCreateServer, wsSetup}) { + return Promise.resolve(opts) + .then(opts => { + const nspObj = wsCreateServer(opts, server) + return Reflect.apply(wsSetup, null, [opts, nspObj]) + }) + .catch(err => { + console.error('Init jsonql Web Socket server error', err) + throw new JsonqlError('jsonqlWsServer', err) + }) +} + /** * This will take the two methods and generate the web socket server * @param {function} wsCreateServer generate the base server @@ -31,18 +55,12 @@ const jsonqlWsCoreConstants = require('./src/share/constants') */ function jsonqlWsServerCore(wsCreateServer, wsSetup) { - return (config, server) => checkConfig(config) - .then(opts => { - const nspObj = wsCreateServer(opts, server) - return Reflect.apply(wsSetup, null, [opts, nspObj]) - }) - .catch(err => { - console.error('Init jsonql Web Socket server error', err) - throw new JsonqlError('jsonqlWsServer', err) - }) + return (config, server) => checkWsConfig(config) + .then(opts => ({ opts, server, wsCreateServer, wsSetup })) + .then(jsonqlWsServerCoreAction) } -// breaking change we export it as a name module +// export every bits out then the downstream build as they want module.exports = { addProperty, getContract, @@ -58,5 +76,6 @@ module.exports = { wsServerConstProps, jsonqlWsCoreConstants, - jsonqlWsServerCore + jsonqlWsServerCore, + jsonqlWsServerCoreAction } diff --git a/packages/ws-server-core/package.json b/packages/ws-server-core/package.json index 006461b9..ee0c0bab 100644 --- a/packages/ws-server-core/package.json +++ b/packages/ws-server-core/package.json @@ -1,22 +1,17 @@ { "name": "jsonql-ws-server-core", - "version": "0.3.0", - "description": "This is the core module that drive the Jsonql Web Socket server, not for direct use.", + "version": "0.4.0", + "description": "This is the core module that drive the Jsonql WS Socket server, not for direct use.", "main": "index.js", "files": [ "index.js", "src" ], "scripts": { - "test": "ava --verbose", + "test": "ava", "prepare": "npm run test", - "test:ws": "DEBUG=jsonql-ws-server* ava ./tests/ws-connect.test.js", - "test:error": "DEBUG=jsonql-ws-server* ava ./tests/ws-connect-error.test.js", - "test:es6": "DEBUG=jsonql-ws-server* ava ./tests/ws-connect-es6.test.js", - "test:jwt": "DEBUG=jsonql-ws-server* ava ./tests/ws-jwt-auth.test.js", - "test:object": "DEBUG=jsonql-ws-server* ava --verbose ./tests/object.test.js", - "contract": "node ./node_modules/jsonql-contract/cmd.js configFile ./tests/fixtures/contract-config.js", - "test:browser": "DEBUG=jsonql* node ./tests/fixtures/browser-test-setup.js" + "test:object": "DEBUG=jsonql-ws-server* ava ./tests/object.test.js", + "contract": "node ./node_modules/jsonql-contract/cmd.js configFile ./tests/fixtures/contract-config.js" }, "keywords": [ "socket.io", @@ -41,14 +36,15 @@ }, "devDependencies": { "ava": "^3.5.0", - "jsonql-contract": "^1.8.7", - "open": "^7.0.2" + "jsonql-contract": "^1.8.7" }, "ava": { "files": [ - "tests/*.test.js", - "!tests/browser/*.*", - "!tests/fixtures/*.*" + "tests/*.test.js" + ], + "ignoredByWatcher": [ + "tests/browser/*.*", + "tests/fixtures/*.*" ], "require": [ "esm" @@ -58,7 +54,7 @@ "failFast": true, "failWithoutAssertions": false, "tap": false, - "compileEnhancements": false + "verbose": true }, "engine": { "node": ">=8" diff --git a/packages/ws-server-core/src/options/index.js b/packages/ws-server-core/src/options/index.js index 77870203..6bc528d3 100644 --- a/packages/ws-server-core/src/options/index.js +++ b/packages/ws-server-core/src/options/index.js @@ -1,16 +1,8 @@ -// there is very limited options there +// WS options const { join } = require('path') const fsx = require('fs-extra') - const { JsonqlValidationError } = require('jsonql-errors') -const { objHasProp } = require('jsonql-utils') -const { - createConfig, - checkConfigAsync, - isContract, - isNotEmpty, - isString -} = require('jsonql-params-validator') +const { createConfig, checkConfigAsync, isString } = require('jsonql-params-validator') const { HSA_ALGO, ENUM_KEY, @@ -19,16 +11,12 @@ const { PRIVATE_KEY, STRING_TYPE, BOOLEAN_TYPE, - OBJECT_TYPE, NUMBER_TYPE, - CHECKER_KEY, PEM_EXT, PUBLIC_KEY_NAME, PRIVATE_KEY_NAME, - DEFAULT_CONTRACT_FILE_NAME, IO_HANDSHAKE_LOGIN, IO_ROUNDTRIP_LOGIN, - CHECKED_KEY, DEFAULT_RESOLVER_DIR, DEFAULT_CONTRACT_DIR, DEFAULT_KEYS_DIR @@ -46,7 +34,8 @@ const debug = getDebug('options') const dirname = process.cwd() // base options -const defaultOptions = { +const wsDefaultOptions = { + appDir: createConfig('', [STRING_TYPE]), // just matching the Koa but not in use at the moment // @TODO this will be moving out shortly after the test done // RS256 this will need to figure out how to distribute the key algorithm: createConfig(HSA_ALGO, [STRING_TYPE]), @@ -57,7 +46,7 @@ const defaultOptions = { [ALIAS_KEY]: 'socketServerType' }), // we require the contract already generated and pass here - contract: createConfig({}, [OBJECT_TYPE]), + // contract: createConfig({}, [OBJECT_TYPE]), this been causing no end of problem, we don't need it! enableAuth: createConfig(false, [BOOLEAN_TYPE]), // this option now is only for passing the key // this cause a bug because this option is always BOOLEAN and STRING TYPE! @@ -66,6 +55,7 @@ const defaultOptions = { resolverDir: createConfig(join(dirname, DEFAULT_RESOLVER_DIR), [STRING_TYPE]), contractDir: createConfig(join(dirname, DEFAULT_CONTRACT_DIR), [STRING_TYPE]), keysDir: createConfig(join(dirname, DEFAULT_KEYS_DIR), [STRING_TYPE]), + // this is for construct the namespace publicMethodDir: createConfig(PUBLIC_KEY, [STRING_TYPE]), // just try this with string type first @@ -77,7 +67,7 @@ const defaultOptions = { }) } -const constProps = { +const wsConstProps = { contract: false, publicKey: false, privateKey: false, @@ -93,38 +83,49 @@ const constProps = { * @param {object} constProps as its * @return {object} checked opts */ -function preCheck(config, defaultOptions, constProps) { - if (objHasProp(config, CHECKED_KEY)) { - const opts = Object.assign(config, constProps) - debug('preCheck checked', opts) - return Promise.resolve(opts) - } - return checkConfigAsync(config, defaultOptions, constProps) +function preCheck(config) { + return checkConfigAsync(config, wsDefaultOptions, wsConstProps) } /** + * We take the step two onward from the wsCheckConfig + * @param {object} config configuration already checked + * @return {promise} resolve to the options that is clean and ready + */ +function initWsOptions(config) { + return Promise.resolve(config) + .then(getContract) + // processing the key + .then(opts => { + if (opts.enableAuth === true) { + // @TODO should get rip of this useJwt as string and + if (isString(opts.useJwt)) { + opts.secret = opts.useJwt + } else if (opts.keysDir) { + 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) + } + } + return opts + }) +} + +/** + * This is a combine that will check the options * @param {object} config user supply * @return {object} promise resolve the opts */ -function checkConfig(config) { - return preCheck(config, defaultOptions, constProps) - .then(getContract) - // processing the key - .then(opts => { - if (opts.enableAuth === true) { - // @TODO should get rip of this useJwt as string and - if (isString(opts.useJwt)) { - opts.secret = opts.useJwt - } else if (opts.keysDir) { - 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) - } - } - return opts - }) +function wsCheckConfig(config) { + return preCheck(config) + .then(initWsOptions) } // breaking change export as name also the options for merge with the upstream server -module.exports = { checkConfig, defaultOptions, constProps } +module.exports = { + initWsOptions, + wsCheckConfig, + wsDefaultOptions, + wsConstProps +} diff --git a/packages/ws-server-core/src/share/add-property.js b/packages/ws-server-core/src/share/add-property.js index a55a11f0..7ea4f9c2 100644 --- a/packages/ws-server-core/src/share/add-property.js +++ b/packages/ws-server-core/src/share/add-property.js @@ -2,7 +2,7 @@ const { EMIT_REPLY_TYPE, SEND_MSG_PROP_NAME, - ON_MESSAGE_PROP_NAME, + // ON_MESSAGE_PROP_NAME, JS_WS_NAME, INIT_CLIENT_PROP_KEY } = require('jsonql-constants') diff --git a/packages/ws-server-core/src/share/constants.js b/packages/ws-server-core/src/share/constants.js index bb50bfc1..64103585 100644 --- a/packages/ws-server-core/src/share/constants.js +++ b/packages/ws-server-core/src/share/constants.js @@ -1,9 +1,9 @@ const { JS_WS_SOCKET_IO_NAME, - JS_WS_NAME, - JS_PRIMUS_NAME, - GO_WS_COOLPY7_NAME + JS_WS_NAME + // JS_PRIMUS_NAME, + // GO_WS_COOLPY7_NAME } = require('jsonql-constants') // short hand const SOCKET_IO = JS_WS_SOCKET_IO_NAME diff --git a/packages/ws-server-core/src/share/get-contract.js b/packages/ws-server-core/src/share/get-contract.js index 63d3f7bc..b7efb965 100644 --- a/packages/ws-server-core/src/share/get-contract.js +++ b/packages/ws-server-core/src/share/get-contract.js @@ -3,7 +3,7 @@ const { join } = require('path') const fsx = require('fs-extra') const { DEFAULT_CONTRACT_FILE_NAME } = require('jsonql-constants') const { isContract } = require('jsonql-utils') -const { JsonqlError } = require('jsonql-errors') +// const { JsonqlError } = require('jsonql-errors') const { CONTRACT_NOT_FOUND_ERR } = require('./constants') // @TODO need to create a generic retry method const TIME_TO_WAIT = 3000 // 3 seconds diff --git a/packages/ws-server-core/src/share/helpers.js b/packages/ws-server-core/src/share/helpers.js index 22da6ce5..ab8d6a53 100644 --- a/packages/ws-server-core/src/share/helpers.js +++ b/packages/ws-server-core/src/share/helpers.js @@ -4,21 +4,26 @@ const { JSONQL_PATH, WS_REPLY_TYPE, WS_EVT_NAME, - WS_DATA_NAME, - ERROR_KEY + WS_DATA_NAME } = require('jsonql-constants') const { isString } = require('jsonql-params-validator') const { JsonqlError, clientErrorsHandler } = require('jsonql-errors') -const { toJson, packError, isObjectHasKey } = require('jsonql-utils') +const { toJson, isObjectHasKey } = require('jsonql-utils') const { MODULE_NAME } = require('./constants') // create debug const debug = require('debug') -const getDebug = name => debug(MODULE_NAME).extend(name) -const _debug = getDebug('helpers') +// const _debug = getDebug('helpers') const WS_KEYS = [ WS_REPLY_TYPE, WS_EVT_NAME, WS_DATA_NAME ] -const { merge } = require('lodash') +// const { merge } = require('lodash') + +/** + * Create the debug instance + * @param {string} name + * @return {function} the debug method + */ +const getDebug = name => debug(MODULE_NAME).extend(name) /** * The ws doesn't have a acknowledge callback like socket.io diff --git a/packages/ws-server-core/src/share/resolve-method.js b/packages/ws-server-core/src/share/resolve-method.js index 596f9215..06167d8e 100644 --- a/packages/ws-server-core/src/share/resolve-method.js +++ b/packages/ws-server-core/src/share/resolve-method.js @@ -1,22 +1,17 @@ // search for the resolver location -const fs = require('fs') -const { join } = require('path') -const { isUndefined } = require('lodash') -const { +/* JsonqlAuthorisationError, JsonqlResolverNotFoundError, - JsonqlResolverAppError, JsonqlValidationError, JsonqlError, finalCatch -} = require('jsonql-errors') -const { - SOCKET_NAME, - DEFAULT_RESOLVER_IMPORT_FILE_NAME, +*/ +const { JsonqlResolverAppError } = require('jsonql-errors') +/* +DEFAULT_RESOLVER_IMPORT_FILE_NAME, MODULE_TYPE -} = require('jsonql-constants') -const { validateSync } = require('jsonql-params-validator') -const { provideUserdata } = require('jsonql-jwt') +*/ +const { SOCKET_NAME } = require('jsonql-constants') const { getResolver } = require('jsonql-resolver') const { getDebug } = require('./helpers') @@ -28,7 +23,7 @@ const debug = getDebug('resolve-method') * similiar to the one in Koa-middleware without the ctx * @param {string} resolverName name to call * @param {array} args arguments - * @param {object} params extracted params + * @param {object} params extracted params <-- why is this NOT IN USE? * @param {object} opts for search later * @param {object} ws the WebSocket instance * @param {object} [userdata=false] userdata @@ -36,7 +31,8 @@ const debug = getDebug('resolve-method') */ const resolveMethod = function(resolverName, args, params, opts, ws, userdata = false) { // the contract is always part of the options here - const fn = getResolver(resolverName, SOCKET_NAME, opts.contract, opts) + const { contract } = opts + const fn = getResolver(resolverName, SOCKET_NAME, contract, opts) return addProperty(fn, resolverName, ws, userdata, opts) .then(tfn => { try { -- Gitee From e72d3649139f667b129eb972e9ed230c8f255bc1 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 15:31:03 +0800 Subject: [PATCH 04/26] add some debug to help determine if some of the things are needed or not --- packages/utils/src/contract.js | 36 +++++++++---------- packages/utils/src/generic.js | 10 +++--- packages/utils/src/node-find-from-contract.js | 4 +-- .../src/share/resolve-method.js | 3 +- packages/ws-server/package.json | 2 +- .../ws-server/src/core/ws-create-server.js | 7 +++- packages/ws-server/src/core/ws-setup.js | 4 +-- 7 files changed, 36 insertions(+), 30 deletions(-) diff --git a/packages/utils/src/contract.js b/packages/utils/src/contract.js index 59d592ae..f36031f0 100644 --- a/packages/utils/src/contract.js +++ b/packages/utils/src/contract.js @@ -30,7 +30,7 @@ export function checkIsContract(contract) { * @return {boolean | object} false when it's not */ export function isContract(contract) { - return checkIsContract(contract) ? contract : false; + return checkIsContract(contract) ? contract : false } /** @@ -41,9 +41,9 @@ export function isContract(contract) { */ export function extractSocketPart(contract) { if (isObjectHasKey(contract, 'socket')) { - return contract.socket; + return contract.socket } - return false; + return false } /** @@ -63,21 +63,21 @@ export function groupByNamespace(contract, fallback = false) { } throw new JsonqlError(`socket not found in contract!`) } - let nspSet = {}; - let size = 0; - let publicNamespace; + let nspSet = {} + let size = 0 + let publicNamespace for (let resolverName in socket) { - let params = socket[resolverName]; - let { namespace } = params; + let params = socket[resolverName] + let { namespace } = params if (namespace) { if (!nspSet[namespace]) { ++size; - nspSet[namespace] = {}; + nspSet[namespace] = {} } - nspSet[namespace][resolverName] = params; + nspSet[namespace][resolverName] = params if (!publicNamespace) { if (params.public) { - publicNamespace = namespace; + publicNamespace = namespace } } } @@ -94,15 +94,15 @@ export function groupByNamespace(contract, fallback = false) { * @return {array} namespaces in order */ export function getNamespaceInOrder(nspSet, publicNamespace) { - let names = []; // need to make sure the order! + let names = [] // need to make sure the order! for (let namespace in nspSet) { if (namespace === publicNamespace) { - names[1] = namespace; + names[1] = namespace } else { - names[0] = namespace; + names[0] = namespace } } - return names; + return names } @@ -115,12 +115,12 @@ export function getNamespaceInOrder(nspSet, publicNamespace) { export function extractArgsFromPayload(payload, type) { switch (type) { case QUERY_NAME: - return payload[QUERY_ARG_NAME]; + return payload[QUERY_ARG_NAME] case MUTATION_NAME: return [ payload[PAYLOAD_PARAM_NAME], payload[CONDITION_PARAM_NAME] - ]; + ] default: throw new JsonqlError(`Unknown ${type} to extract argument from!`) } @@ -135,7 +135,7 @@ export function extractArgsFromPayload(payload, type) { */ export function extractParamsFromContract(contract, type, name) { try { - const result = contract[type][name]; + const result = contract[type][name] // debug('extractParamsFromContract', result) if (!result) { // debug(name, type, contract) diff --git a/packages/utils/src/generic.js b/packages/utils/src/generic.js index e882d006..4a5f208e 100644 --- a/packages/utils/src/generic.js +++ b/packages/utils/src/generic.js @@ -10,10 +10,10 @@ import trim from 'lodash-es/trim' * @param {*} value to check against * @return {boolean} true on found */ -export const inArray = (arr, value) => !!arr.filter(a => a === value).length; +export const inArray = (arr, value) => !!arr.filter(a => a === value).length // quick and dirty to turn non array to array -export const toArray = (arg) => isArray(arg) ? arg : [arg]; +export const toArray = (arg) => isArray(arg) ? arg : [arg] /** * parse string to json or just return the original value if error happened @@ -24,7 +24,7 @@ const parse = function(n) { try { return JSON.parse(n) } catch(e) { - return n; + return n } } @@ -39,7 +39,7 @@ export const isObjectHasKey = function(obj, key) { return inArray(keys, key) } catch(e) { // @BUG when the obj is not an OBJECT we got some weird output - return false; + return false /* console.info('obj', obj) console.error(e) @@ -83,7 +83,7 @@ export const toJson = (n) => { * @return {boolean} */ export const isNotEmpty = function(param) { - return param !== undefined && param !== false && param !== null && trim(param) !== ''; + return param !== undefined && param !== false && param !== null && trim(param) !== '' } /** diff --git a/packages/utils/src/node-find-from-contract.js b/packages/utils/src/node-find-from-contract.js index 643ef338..b206ba6e 100644 --- a/packages/utils/src/node-find-from-contract.js +++ b/packages/utils/src/node-find-from-contract.js @@ -13,8 +13,8 @@ import fs from 'fs' export function findFromContract(type, name, contract) { if (contract[type] && contract[type][name] && contract[type][name].file) { if (fs.existsSync(contract[type][name].file)) { - return contract[type][name].file; + return contract[type][name].file } } - return false; + return false } diff --git a/packages/ws-server-core/src/share/resolve-method.js b/packages/ws-server-core/src/share/resolve-method.js index 06167d8e..4c13d89a 100644 --- a/packages/ws-server-core/src/share/resolve-method.js +++ b/packages/ws-server-core/src/share/resolve-method.js @@ -23,13 +23,14 @@ const debug = getDebug('resolve-method') * similiar to the one in Koa-middleware without the ctx * @param {string} resolverName name to call * @param {array} args arguments - * @param {object} params extracted params <-- why is this NOT IN USE? + * @param {object} params from contract.json <-- why is this NOT IN USE? * @param {object} opts for search later * @param {object} ws the WebSocket instance * @param {object} [userdata=false] userdata * @return {promise} depends on the contract */ const resolveMethod = function(resolverName, args, params, opts, ws, userdata = false) { + debug('wsServerCore.resolveMethod', params) // check what is this then decided what to do later // the contract is always part of the options here const { contract } = opts const fn = getResolver(resolverName, SOCKET_NAME, contract, opts) diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json index 32e0fe8e..1d9c9d68 100755 --- a/packages/ws-server/package.json +++ b/packages/ws-server/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-ws-server", - "version": "1.5.3", + "version": "1.6.0", "description": "Setup WebSocket server for the jsonql to run on the same host, automatic generate public / private channel using contract", "main": "index.js", "files": [ diff --git a/packages/ws-server/src/core/ws-create-server.js b/packages/ws-server/src/core/ws-create-server.js index a9e989e7..74db01d4 100644 --- a/packages/ws-server/src/core/ws-create-server.js +++ b/packages/ws-server/src/core/ws-create-server.js @@ -3,11 +3,11 @@ const url = require('url') const WebSocket = require('ws') // need to move the method back here const { createVerifyClient } = require('./verify-client') - const { getNamespace, getDebug } = require('jsonql-ws-server-core') const debug = getDebug('ws-setup') /** + * Get the WS namespace instance to handle the call * @param {array} namespace string * @param {object} config configuration * @return {array} of nsps @@ -81,6 +81,11 @@ function wsCreateServer(config, server) { } */ }) + // add one more listener here to check out what's wrong with the server + server.on('error', function(err) { + debug(`ws server.on error`, err) + }) + return nsps } diff --git a/packages/ws-server/src/core/ws-setup.js b/packages/ws-server/src/core/ws-setup.js index 42d40ba5..14608a1e 100644 --- a/packages/ws-server/src/core/ws-setup.js +++ b/packages/ws-server/src/core/ws-setup.js @@ -1,5 +1,5 @@ -// ws setup -const { finalCatch } = require('jsonql-errors') +// ws setup all the listener to handle the incoming calls +// const { finalCatch } = require('jsonql-errors') const { packError, groupByNamespace } = require('jsonql-utils') const { isNotEmpty, validateAsync } = require('jsonql-params-validator') const { -- Gitee From 16b1b0a9628d03696f86ec5d0773529de5273a7c Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 15:41:26 +0800 Subject: [PATCH 05/26] clean up and hook to the module for testing --- packages/ws-server-core/index.js | 8 +++++--- packages/ws-server/client.js | 1 + packages/ws-server/index.js | 24 +++++++++++++++++++----- packages/ws-server/package.json | 12 +++++++----- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/packages/ws-server-core/index.js b/packages/ws-server-core/index.js index 22f90819..32c0dfcb 100644 --- a/packages/ws-server-core/index.js +++ b/packages/ws-server-core/index.js @@ -55,9 +55,11 @@ function jsonqlWsServerCoreAction({opts, server, wsCreateServer, wsSetup}) { */ function jsonqlWsServerCore(wsCreateServer, wsSetup) { - return (config, server) => checkWsConfig(config) - .then(opts => ({ opts, server, wsCreateServer, wsSetup })) - .then(jsonqlWsServerCoreAction) + return (config, server) => ( + checkWsConfig(config) + .then(opts => ({ opts, server, wsCreateServer, wsSetup })) + .then(jsonqlWsServerCoreAction) + ) } // export every bits out then the downstream build as they want diff --git a/packages/ws-server/client.js b/packages/ws-server/client.js index a5829264..eed66c50 100644 --- a/packages/ws-server/client.js +++ b/packages/ws-server/client.js @@ -1,6 +1,7 @@ // we also provide a node client here const WebSocket = require('ws') const { TOKEN_PARAM_NAME } = require('jsonql-constants') + /** * Create a client with auth token * @param {string} url start with ws:// @TODO check this? diff --git a/packages/ws-server/index.js b/packages/ws-server/index.js index f145c6bc..77178c03 100644 --- a/packages/ws-server/index.js +++ b/packages/ws-server/index.js @@ -3,15 +3,28 @@ const { wsSetup, wsCreateServer } = require('./src') const { jsonqlWsServerCore, - getDebug, + jsonqlWsServerCoreAction, + // getDebug, wsServerDefaultOptions, wsServerConstProps -} = require('jsonql-ws-server-core') -const { JsonqlError } = require('jsonql-errors') -const debug = getDebug('main') +} = require('../ws-server-core') +// require('jsonql-ws-server-core') +// const { JsonqlError } = require('jsonql-errors') +// const debug = getDebug('main') /** - * @TODO this should export as a named export + * This is the method that is the actual create server without the config check + * @param {object} opts the already checked configuration + * @param {object} server the http server instance + * @return {object} the jsonql ws server instance + */ +function jsonqlWsServerAction(opts, server) { + const params = { opts, server, wsCreateServer, wsSetup } + return jsonqlWsServerCoreAction(params) +} + +/** + * The main method * @param {object} config this is now diverse from the middleware setup * @param {string} config.serverType socket.io or ws in the background * @param {object} config.options the actual options to pass to the underlying setups @@ -27,6 +40,7 @@ function jsonqlWsServer(config, server) { // breaking change we export it as a name module module.exports = { jsonqlWsServer, + jsonqlWsServerAction, // props export wsServerDefaultOptions, wsServerConstProps diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json index 1d9c9d68..38ae7a8e 100755 --- a/packages/ws-server/package.json +++ b/packages/ws-server/package.json @@ -8,7 +8,7 @@ "src" ], "scripts": { - "test": "ava --verbose", + "test": "ava ", "prepare": "npm run test", "test:ws": "DEBUG=jsonql-ws-server* ava ./tests/ws-connect.test.js", "test:error": "DEBUG=jsonql-ws-server* ava ./tests/ws-connect-error.test.js", @@ -37,9 +37,11 @@ }, "ava": { "files": [ - "tests/*.test.js", - "!tests/browser/*.*", - "!tests/fixtures/*.*" + "tests/*.test.js" + ], + "ignoredByWatcher": [ + "tests/browser/*.*", + "tests/fixtures/*.*" ], "require": [ "esm" @@ -49,7 +51,7 @@ "failFast": true, "failWithoutAssertions": false, "tap": false, - "compileEnhancements": false + "verbose": true }, "engine": { "node": ">=8" -- Gitee From 89c55caa6b210a18cdd5c65ffc89bca2196ee645 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 15:55:07 +0800 Subject: [PATCH 06/26] tested passed and ready to publish ws-server-core first --- packages/ws-server-core/index.js | 14 ++++++++------ packages/ws-server-core/src/index.js | 15 ++++++++++----- packages/ws-server-core/src/options/index.js | 6 +++--- packages/ws-server/tests/ws-connect.test.js | 16 ++++++++-------- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/packages/ws-server-core/index.js b/packages/ws-server-core/index.js index 32c0dfcb..7f164e64 100644 --- a/packages/ws-server-core/index.js +++ b/packages/ws-server-core/index.js @@ -2,7 +2,8 @@ // which is completely useless for us if there is no namespace const { JsonqlError } = require('jsonql-errors') const { - checkWsConfig, + initWsOptions, + wsCheckConfig, wsServerDefaultOptions, wsServerConstProps } = require('./src') @@ -36,10 +37,11 @@ const jsonqlWsCoreConstants = require('./src/share/constants') * @return {promise} checked config */ function jsonqlWsServerCoreAction({opts, server, wsCreateServer, wsSetup}) { - return Promise.resolve(opts) - .then(opts => { - const nspObj = wsCreateServer(opts, server) - return Reflect.apply(wsSetup, null, [opts, nspObj]) + + return initWsOptions(opts) + .then(_opts => { + const nspObj = wsCreateServer(_opts, server) + return Reflect.apply(wsSetup, null, [_opts, nspObj]) }) .catch(err => { console.error('Init jsonql Web Socket server error', err) @@ -56,7 +58,7 @@ function jsonqlWsServerCoreAction({opts, server, wsCreateServer, wsSetup}) { function jsonqlWsServerCore(wsCreateServer, wsSetup) { return (config, server) => ( - checkWsConfig(config) + wsCheckConfig(config) .then(opts => ({ opts, server, wsCreateServer, wsSetup })) .then(jsonqlWsServerCoreAction) ) diff --git a/packages/ws-server-core/src/index.js b/packages/ws-server-core/src/index.js index a7efb186..7b8aaeb3 100644 --- a/packages/ws-server-core/src/index.js +++ b/packages/ws-server-core/src/index.js @@ -1,14 +1,19 @@ // re-export here - -const { checkConfig, defaultOptions, constProps } = require('./options') +const { + initWsOptions, + wsCheckConfig, + wsDefaultOptions, + wsConstProps +} = require('./options') // rename it before export -const wsServerDefaultOptions = defaultOptions -const wsServerConstProps = constProps +const wsServerDefaultOptions = wsDefaultOptions +const wsServerConstProps = wsConstProps // re-export module.exports = { // rename them wsServerDefaultOptions, wsServerConstProps, // rest of the exports - checkConfig + initWsOptions, + wsCheckConfig } diff --git a/packages/ws-server-core/src/options/index.js b/packages/ws-server-core/src/options/index.js index 6bc528d3..a79699e2 100644 --- a/packages/ws-server-core/src/options/index.js +++ b/packages/ws-server-core/src/options/index.js @@ -28,8 +28,8 @@ const { SECRET_MISSING_ERR } = require('../share/constants') const { getContract } = require('../share/get-contract') -const { getDebug } = require('../share/helpers') -const debug = getDebug('options') +// const { getDebug } = require('../share/helpers') +// const debug = getDebug('options') const dirname = process.cwd() @@ -113,7 +113,7 @@ function initWsOptions(config) { } /** - * This is a combine that will check the options + * This is a combine method that will check the options * @param {object} config user supply * @return {object} promise resolve the opts */ diff --git a/packages/ws-server/tests/ws-connect.test.js b/packages/ws-server/tests/ws-connect.test.js index 541b1a94..e6b4c1b8 100644 --- a/packages/ws-server/tests/ws-connect.test.js +++ b/packages/ws-server/tests/ws-connect.test.js @@ -7,7 +7,7 @@ const fsx = require('fs-extra') const wsNodeClient = require('../client') const wsServer = require('./fixtures/server') -const { JSONQL_PATH, ERROR_TYPE } = require('jsonql-constants') +const { JSONQL_PATH } = require('jsonql-constants') const debug = require('debug')('jsonql-ws-server:test:ws') const contractDir = join(__dirname, 'fixtures', 'contract') @@ -16,17 +16,17 @@ const contract = fsx.readJsonSync(contractFile); const { extractWsPayload } = require('jsonql-ws-server-core') const createPayload = require('./fixtures/create-payload') -const port = 8898; -const msg = 'Something'; -let ctn = 0; +const port = 8898 +const msg = 'Something' +// let ctn = 0; test.before(async t => { const { app, io } = await wsServer({ contractDir, contract }) - t.context.io = io; - t.context.server = app; + t.context.io = io + t.context.server = app t.context.server.listen(port) t.context.client = wsNodeClient(`ws://localhost:${port}/${JSONQL_PATH}`) @@ -57,7 +57,7 @@ test.cb('Grouping all test together as one because the way ws reponse to on.mess switch (json.resolverName) { case 'wsHandler': - ++tested; + ++tested t.truthy(json.data, 'wsHandler should reply with a message') if (tested > 1) { t.end() @@ -65,7 +65,7 @@ test.cb('Grouping all test together as one because the way ws reponse to on.mess break; case 'chatroom': t.truthy(json.data, 'chatroom should reply with a message') - ++tested; + ++tested if (tested > 1) { t.end() } -- Gitee From 3cf7f583a2e81976514e0eeae3983a9ea8ad41ac Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 16:02:07 +0800 Subject: [PATCH 07/26] jsonql-ws-server 1.6.0 --- packages/ws-server/index.js | 4 ++-- packages/ws-server/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/ws-server/index.js b/packages/ws-server/index.js index 77178c03..4b52fb25 100644 --- a/packages/ws-server/index.js +++ b/packages/ws-server/index.js @@ -7,8 +7,8 @@ const { // getDebug, wsServerDefaultOptions, wsServerConstProps -} = require('../ws-server-core') -// require('jsonql-ws-server-core') +} = require('jsonql-ws-server-core') // require('../ws-server-core') + // const { JsonqlError } = require('jsonql-errors') // const debug = getDebug('main') diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json index 38ae7a8e..996a0234 100755 --- a/packages/ws-server/package.json +++ b/packages/ws-server/package.json @@ -27,7 +27,7 @@ "author": "Joel Chu ", "license": "MIT", "dependencies": { - "jsonql-ws-server-core": "^0.3.0", + "jsonql-ws-server-core": "^0.4.0", "ws": "^7.2.1" }, "devDependencies": { -- Gitee From f59fc2ef2f0146abfd9c83fd15956ae22507dde5 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 16:40:55 +0800 Subject: [PATCH 08/26] update the ws-client-core to get rip of all the pre post check and break up the modules --- packages/ws-client-core/index.js | 3 +- packages/ws-client-core/package.json | 22 +++++---- .../ws-client-core/src/options/defaults.js | 1 + packages/ws-client-core/src/options/index.js | 47 +++++++++++-------- .../src/share/client-event-handler.js | 4 +- 5 files changed, 45 insertions(+), 32 deletions(-) diff --git a/packages/ws-client-core/index.js b/packages/ws-client-core/index.js index cbd477d1..013b08a0 100644 --- a/packages/ws-client-core/index.js +++ b/packages/ws-client-core/index.js @@ -1,10 +1,11 @@ // This is the module entry point import jsonqlWsClientCore from './src/api' -import { wsCoreDefaultOptions, wsCoreConstProps } from './src/options' +import { wsCoreDefaultOptions, wsCoreConstProps, postWsOptions } from './src/options' // export with name interface export { wsCoreDefaultOptions, wsCoreConstProps, + postWsOptions, jsonqlWsClientCore } diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json index 8e0f7892..a2aca1cc 100644 --- a/packages/ws-client-core/package.json +++ b/packages/ws-client-core/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-ws-client-core", - "version": "0.4.3", + "version": "0.5.0", "description": "This is the jsonql Web Socket client core library for Node and Browser. Not for direct use.", "main": "main.js", "module": "index.js", @@ -11,12 +11,12 @@ "share.js" ], "scripts": { - "test": "ava --verbose", + "test": "ava ", "prepare": "npm run test", "update:version": "node ./build.js", - "test:evt": "ava --verbose ./tests/event.test.js", - "test:node": "DEBUG=jsonql-ws-* ava --verbose ./tests/test-node.test.js", - "test:opt": "DEBUG=jsonql-ws-* ava --verbose ./tests/options.test.js", + "test:evt": "ava ./tests/event.test.js", + "test:node": "DEBUG=jsonql-ws-* ava ./tests/test-node.test.js", + "test:opt": "DEBUG=jsonql-ws-* ava ./tests/options.test.js", "contract": "node ./node_modules/jsonql-contract/cmd.js configFile ./tests/fixtures/contract-config.js", "contract:auth": "node ./node_modules/jsonql-contract/cmd.js configFile ./tests/fixtures/contract-config-auth.js" }, @@ -31,10 +31,12 @@ "license": "MIT", "ava": { "files": [ - "tests/*.test.js", - "!tests/helpers/*.*", - "!tests/fixtures/*.*", - "!tests/jwt/*.*" + "tests/*.test.js" + ], + "ignoredByWatcher": [ + "tests/helpers/*.*", + "tests/fixtures/*.*", + "tests/jwt/*.*" ], "require": [ "esm" @@ -44,7 +46,7 @@ "failFast": true, "failWithoutAssertions": false, "tap": false, - "compileEnhancements": false + "verbose": true }, "engine": { "node": ">=8" diff --git a/packages/ws-client-core/src/options/defaults.js b/packages/ws-client-core/src/options/defaults.js index f4e67ece..7fa909d7 100644 --- a/packages/ws-client-core/src/options/defaults.js +++ b/packages/ws-client-core/src/options/defaults.js @@ -40,6 +40,7 @@ const wsCoreDefaultOptions = { // constant props const wsCoreConstProps = { + // contract: null, eventEmitter: null, // we unify the two different client into one now // only expect different parameter diff --git a/packages/ws-client-core/src/options/index.js b/packages/ws-client-core/src/options/index.js index a99b208c..e16401a1 100644 --- a/packages/ws-client-core/src/options/index.js +++ b/packages/ws-client-core/src/options/index.js @@ -1,36 +1,32 @@ // create options -import { checkConfig } from 'jsonql-params-validator' +import { checkConfigAsync } from 'jsonql-params-validator' import { wsCoreDefaultOptions, wsCoreConstProps } from './defaults' -import { - fixWss, - getHostName, - objHasProp, - postConfigCheck -} from '../utils' +import { fixWss, getHostName } from '../utils' /** * wrapper method to check this already did the pre check * @param {object} config user supply config * @param {object} defaultOptions for checking - * @param {object} cProps user supply const props + * @param {object} constProps user supply const props * @return {promise} resolve to the checked opitons */ -function checkOptionsWrapper(config, defaultOptions, cProps) { - const constProps = Object.assign(wsCoreConstProps, cProps) - const checkMap = Object.assign(wsCoreDefaultOptions, defaultOptions) +function checkOptionsWrapper(config, defaultOptions, constProps) { + const wsConstProps = Object.assign(wsCoreConstProps, constProps) + const defaultCheckOptions = Object.assign(wsCoreDefaultOptions, defaultOptions) + /* const fn = postConfigCheck(checkMap, constProps, checkConfig) return fn(config) + */ + return checkConfigAsync(config, defaultCheckOptions, wsConstProps) } /** - * check the configuration - * @param {object} config user supplied configuration - * @param {object} defaultOptions the check map - * @param {object} constProps developer supplied configuration - * @return {object} after checked + * Taking the then part from the method below + * @param {object} opts + * @return {promise} opts all done */ -function checkWsCoreOptions(config, defaultOptions, constProps) { - return checkOptionsWrapper(config, defaultOptions, constProps) +function postWsOptions(opts) { + return Promise.resolve(opts) .then(opts => { if (!opts.hostname) { opts.hostname = getHostName() @@ -43,9 +39,22 @@ function checkWsCoreOptions(config, defaultOptions, constProps) { }) } +/** + * check the configuration + * @param {object} config user supplied configuration + * @param {object} defaultOptions the check map + * @param {object} constProps developer supplied configuration + * @return {object} after checked + */ +function checkWsCoreOptions(config, defaultOptions, constProps) { + return checkOptionsWrapper(config, defaultOptions, constProps) + .then(postWsOptions) +} + export { wsCoreDefaultOptions, wsCoreConstProps, - checkWsCoreOptions + checkWsCoreOptions, + postWsOptions } 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 40d81965..64294738 100644 --- a/packages/ws-client-core/src/share/client-event-handler.js +++ b/packages/ws-client-core/src/share/client-event-handler.js @@ -5,12 +5,12 @@ import { ERROR_PROP_NAME, RESULT_PROP_NAME, - LOGIN_EVENT_NAME, + // LOGIN_EVENT_NAME, LOGOUT_EVENT_NAME, NOT_LOGIN_ERR_MSG, ON_ERROR_PROP_NAME, ON_RESULT_PROP_NAME, - ON_MESSAGE_PROP_NAME, + // ON_MESSAGE_PROP_NAME, } from 'jsonql-constants' import { EMIT_EVT, SOCKET_IO, WS } from '../options/constants' import { createEvt, clearMainEmitEvt } from '../utils' -- Gitee From f91361ed02d0234a95972a28b2fee4ba7afbb666 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 17:00:38 +0800 Subject: [PATCH 09/26] getting the export ready to publish --- packages/ws-client-core/index.js | 7 +-- packages/ws-client-core/package.json | 8 ++-- packages/ws-client-core/src/api.js | 47 ++++++++++++------- packages/ws-client-core/src/utils/helpers.js | 2 +- .../src/utils/process-contract.js | 2 +- 5 files changed, 40 insertions(+), 26 deletions(-) diff --git a/packages/ws-client-core/index.js b/packages/ws-client-core/index.js index 013b08a0..90e45612 100644 --- a/packages/ws-client-core/index.js +++ b/packages/ws-client-core/index.js @@ -1,11 +1,12 @@ // This is the module entry point -import jsonqlWsClientCore from './src/api' +import { wsClientCore, wsClientCoreAction } from './src/api' import { wsCoreDefaultOptions, wsCoreConstProps, postWsOptions } from './src/options' -// export with name interface +// export export { wsCoreDefaultOptions, wsCoreConstProps, postWsOptions, - jsonqlWsClientCore + wsClientCore, + wsClientCoreAction } diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json index a2aca1cc..a7b14bf7 100644 --- a/packages/ws-client-core/package.json +++ b/packages/ws-client-core/package.json @@ -56,14 +56,14 @@ "jsonql-errors": "^1.1.10", "jsonql-params-validator": "^1.5.2", "jsonql-utils": "^0.9.7", - "nb-event-service": "^1.9.0" + "nb-event-service": "^1.9.1" }, "devDependencies": { - "ava": "^2.4.0", + "ava": "^3.5.0", "esm": "^3.2.25", "fs-extra": "^8.1.0", - "jsonql-contract": "^1.8.6", - "jsonql-ws-server": "^1.5.3", + "jsonql-contract": "^1.8.7", + "jsonql-ws-server": "^1.6.0", "kefir": "^3.8.6", "ws": "^7.2.1" }, diff --git a/packages/ws-client-core/src/api.js b/packages/ws-client-core/src/api.js index 7c4533ee..f177b2cf 100644 --- a/packages/ws-client-core/src/api.js +++ b/packages/ws-client-core/src/api.js @@ -44,6 +44,30 @@ const getLogFn = opts => { return opts } +/** + * 0.5.0 we break up the wsClientCore in two parts one without the config check + * @param {function} socketClientResolver + * @param {object} config the already checked config + */ +export function wsClientCoreAction(socketClientResolver, config) { + return Promise.resolve(config) + .then(getLogFn) + .then(opts => ({ + opts, + nspMap: processContract(opts), + ee: getEventEmitter(opts) + })) + .then( + ({opts, nspMap, ee}) => socketClientResolver(opts, nspMap, ee) + ) + .then( + ({opts, nspMap, ee}) => generator(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} socketClientResolver this is the one method export by various clients @@ -51,23 +75,12 @@ const getLogFn = opts => { * @param {object} [constProps={}] add this to supply the constProps from the downstream client * @return {object} the wsClient instance with all the available API */ -export default function wsClientCore(socketClientResolver, defaultOptions = {}, constProps = {}) { +export function wsClientCore(socketClientResolver, defaultOptions = {}, constProps = {}) { // we need to inject property to this client later // therefore we need to do it this way - return (config = {}) => checkWsCoreOptions(config, defaultOptions, constProps) - .then(getLogFn) - .then(opts => ({ - opts, - nspMap: processContract(opts), - ee: getEventEmitter(opts) - })) - .then( - ({opts, nspMap, ee}) => socketClientResolver(opts, nspMap, ee) - ) - .then( - ({opts, nspMap, ee}) => generator(opts, nspMap, ee) - ) - .catch(err => { - console.error(`jsonql-ws-core-client init error`, err) - }) + return (config = {}) => ( + checkWsCoreOptions(config, defaultOptions, constProps) + .then(opts => wsClientCoreAction(socketClientResolver, opts)) + ) + } diff --git a/packages/ws-client-core/src/utils/helpers.js b/packages/ws-client-core/src/utils/helpers.js index 36654004..0e1356a6 100644 --- a/packages/ws-client-core/src/utils/helpers.js +++ b/packages/ws-client-core/src/utils/helpers.js @@ -8,7 +8,7 @@ export const fixWss = (url, serverType) => { if (serverType === JS_WS_NAME) { return url.replace('http://', 'ws://') } - return url; + return url } /** diff --git a/packages/ws-client-core/src/utils/process-contract.js b/packages/ws-client-core/src/utils/process-contract.js index caa9a561..92f81ca5 100644 --- a/packages/ws-client-core/src/utils/process-contract.js +++ b/packages/ws-client-core/src/utils/process-contract.js @@ -24,7 +24,7 @@ const getResolverList = contract => { * @return {object} sorted list */ export default function processContract(opts) { - const { contract, enableAuth } = opts; + const { contract, enableAuth } = opts if (enableAuth) { return groupByNamespace(contract) } -- Gitee From cfe54a40c692ad3139a96c2b40e51d582519d68e Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 17:11:02 +0800 Subject: [PATCH 10/26] reimport the new modules and setup a new interface for hook up with others --- packages/@jsonql/ws/index.js | 5 +++-- packages/@jsonql/ws/module.js | 14 ++++++++++++ packages/@jsonql/ws/package.json | 38 +++++++++++++++++--------------- 3 files changed, 37 insertions(+), 20 deletions(-) create mode 100644 packages/@jsonql/ws/module.js diff --git a/packages/@jsonql/ws/index.js b/packages/@jsonql/ws/index.js index 075c36bc..105e315e 100644 --- a/packages/@jsonql/ws/index.js +++ b/packages/@jsonql/ws/index.js @@ -1,11 +1,12 @@ // this is the module entry point for ES6 for client // the main will point to the node.js server side setup -import { jsonqlWsClientCore } from 'jsonql-ws-client-core' + +import { wsClientCore } from 'jsonql-ws-client-core' import wsClientResolver from './src/ws-client-resolver' import { wsClientAppProps, wsClientConstProps } from './src/options' // export back the function and that's it export default function wsBrowserClient(config = {}, constProps = {}) { - const initMethod = jsonqlWsClientCore(wsClientResolver, wsClientAppProps, Object.assign(wsClientConstProps, constProps)) + const initMethod = wsClientCore(wsClientResolver, wsClientAppProps, Object.assign(wsClientConstProps, constProps)) return initMethod(config) } diff --git a/packages/@jsonql/ws/module.js b/packages/@jsonql/ws/module.js new file mode 100644 index 00000000..7098be55 --- /dev/null +++ b/packages/@jsonql/ws/module.js @@ -0,0 +1,14 @@ +// this is a new interface that takes the already check config +// and init the ws client + +import { + wsCoreDefaultOptions, + wsCoreConstProps, + postWsOptions, + wsClientCoreAction +} from 'jsonql-ws-client-core' + +// import { jsonqlWsClientCore } from 'jsonql-ws-client-core' + +import wsClientResolver from './src/ws-client-resolver' +import { wsClientAppProps, wsClientConstProps } from './src/options' \ No newline at end of file diff --git a/packages/@jsonql/ws/package.json b/packages/@jsonql/ws/package.json index a61a11e0..65174879 100644 --- a/packages/@jsonql/ws/package.json +++ b/packages/@jsonql/ws/package.json @@ -1,6 +1,6 @@ { "name": "@jsonql/ws", - "version": "1.0.11", + "version": "1.1.0", "description": "jsonql WS (WebSocket) client module for browser / node", "main": "node.js", "browser": "dist/jsonql-ws.umd.js", @@ -13,7 +13,7 @@ "node.js.map" ], "scripts": { - "test": "ava --verbose", + "test": "ava", "prepare": "npm run build", "build:cjs": "TARGET=cjs rollup -c", "build:umd": "TARGET=umd rollup -c", @@ -21,11 +21,11 @@ "build": "NODE_ENV=production npm run build:cjs && NODE_ENV=production npm run build:umd", "test:browser:basic": "npm run build:umd && DEBUG=jsonql-ws-client*,server-io-core* node ./tests/browser/run-qunit.js", "test:browser:auth": "npm run build:umd && DEBUG=jsonql-ws-* NODE_ENV=ws-auth node ./tests/browser/run-qunit.js", - "test:opt": "ava --verbose ./tests/opt.test.js", + "test:opt": "ava ./tests/opt.test.js", "test:basic": "npm run build:cjs && DEBUG=jsonql-ws-client* ava ./tests/ws-client-basic.test.js", "test:auth": "npm run build:cjs && DEBUG=jsonql-ws-client*,-jsonql-ws-client:nb-event-service ava ./tests/ws-client-auth.test.js", "test:login": "npm run build:cjs && DEBUG=jsonql-ws*,-jsonql-ws-client:nb-event-service ava ./tests/ws-client-auth-login.test.js", - "test:chain": "npm run build:cjs && DEBUG=jsonql-ws-client*,-jsonql-ws-client:nb-event-service ava --verbose ./tests/ws-client-chain.test.js" + "test:chain": "npm run build:cjs && DEBUG=jsonql-ws-client*,-jsonql-ws-client:nb-event-service ava ./tests/ws-client-chain.test.js" }, "keywords": [ "jsonql", @@ -45,43 +45,45 @@ "jsonql-jwt": "^1.3.8", "jsonql-params-validator": "^1.5.2", "jsonql-utils": "^0.9.7", - "jsonql-ws-client-core": "^0.4.3", + "jsonql-ws-client-core": "^0.5.0", "ws": "^7.2.1" }, "devDependencies": { - "ava": "^2.4.0", + "ava": "^3.5.0", "esm": "^3.2.25", "fs-extra": "^8.1.0", "glob": "^7.1.6", - "jsonql-contract": "^1.8.6", - "jsonql-koa": "^1.5.6", - "jsonql-ws-server": "^1.5.3", + "jsonql-contract": "^1.8.7", + "jsonql-koa": "^1.6.2", + "jsonql-ws-server": "^1.6.0", "kefir": "^3.8.6", "koa": "^2.11.0", "koa-bodyparser": "^4.2.1", - "rollup": "^1.27.14", + "rollup": "^1.32.0", "rollup-plugin-alias": "^2.2.0", "rollup-plugin-async": "^1.2.0", "rollup-plugin-buble": "^0.19.8", "rollup-plugin-bundle-size": "^1.0.3", "rollup-plugin-commonjs": "^10.1.0", - "rollup-plugin-copy": "^3.1.0", + "rollup-plugin-copy": "^3.3.0", "rollup-plugin-json": "^4.0.0", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-replace": "^2.2.0", "rollup-plugin-serve": "^1.0.1", - "rollup-plugin-terser": "^5.1.3", + "rollup-plugin-terser": "^5.2.0", "rollup-pluginutils": "^2.8.2", - "server-io-core": "^1.2.0" + "server-io-core": "^1.3.1" }, "ava": { "files": [ - "tests/*.test.js", - "!tests/helpers/*.*", - "!tests/fixtures/*.*", - "!tests/jwt/*.*" + "tests/*.test.js" + ], + "ignoredByWatcher": [ + "tests/helpers/*.*", + "tests/fixtures/*.*", + "tests/jwt/*.*" ], "require": [ "esm" @@ -91,7 +93,7 @@ "failFast": true, "failWithoutAssertions": false, "tap": false, - "compileEnhancements": false + "verbose": false }, "engine": { "node": ">=8" -- Gitee From feae23cdd2ac8d21361c32fa4fb86139e58545c0 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 17:21:04 +0800 Subject: [PATCH 11/26] existing interface all working --- packages/@jsonql/ws/dist/jsonql-ws-client.umd.js | 2 +- packages/@jsonql/ws/main.js | 2 ++ packages/@jsonql/ws/main.js.map | 1 + packages/@jsonql/ws/package.json | 4 +++- packages/@jsonql/ws/rollup.config.js | 9 +++++++-- packages/@jsonql/ws/src/node.js | 4 ++-- 6 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 packages/@jsonql/ws/main.js create mode 100644 packages/@jsonql/ws/main.js.map diff --git a/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js b/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js index ba2fdbbd..d68b2b05 100644 --- a/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js +++ b/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js @@ -1,2 +1,2 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).jsonqlWsClient=e()}(this,(function(){"use strict";var t=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 406},r.name.get=function(){return"Jsonql406Error"},Object.defineProperties(e,r),e}(Error),e=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"Jsonql500Error"},Object.defineProperties(e,r),e}(Error),r=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 403},r.name.get=function(){return"JsonqlForbiddenError"},Object.defineProperties(e,r),e}(Error),n=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlAuthorisationError"},Object.defineProperties(e,r),e}(Error),o=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlContractAuthError"},Object.defineProperties(e,r),e}(Error),a=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"JsonqlResolverAppError"},Object.defineProperties(e,r),e}(Error),i=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 404},r.name.get=function(){return"JsonqlResolverNotFoundError"},Object.defineProperties(e,r),e}(Error),u=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlEnumError"},Object.defineProperties(e,r),e}(Error),c=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlTypeError"},Object.defineProperties(e,r),e}(Error),f=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlCheckerError"},Object.defineProperties(e,r),e}(Error),s=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(e,r),e}(Error),l="data",p="error",h="jsonql",v="query",g="mutation",d="socket",y="TS",b="type",_="optional",m="enumv",w="args",j="checker",S="alias",O="__checked__",k="No message",E="__login__",$="__logout__",T="emit",A="acknowledge",P="error",z="nspSet",N="publicNamespace",C="onMessage",x="onResult",q="onError",R="onReady",M="onLogin",F="message",W="result",L="error",J="ready",I="login",U="token",D=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0},statusCode:{configurable:!0}};return r.name.get=function(){return"JsonqlError"},r.statusCode.get=function(){return-1},Object.defineProperties(e,r),e}(Error),H=function(t){function e(r,n){t.call(this,n),this.statusCode=r,this.className=e.name}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlServerError"},Object.defineProperties(e,r),e}(Error);function V(l){if(Array.isArray(l))throw new s("",l);var p=l.message||k,h=l.detail||l;switch(!0){case l instanceof t:throw new t(p,h);case l instanceof e:throw new e(p,h);case l instanceof r:throw new r(p,h);case l instanceof n:throw new n(p,h);case l instanceof o:throw new o(p,h);case l instanceof a:throw new a(p,h);case l instanceof i:throw new i(p,h);case l instanceof u:throw new u(p,h);case l instanceof c:throw new c(p,h);case l instanceof f:throw new f(p,h);case l instanceof s:throw new s(p,h);case l instanceof H:throw new H(p,h);default:throw new D(p,h)}}var B="socket.io",Y=T,K="UKNNOWN RESULT!",G="on",Q="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},X="object"==typeof Q&&Q&&Q.Object===Object&&Q,Z="object"==typeof self&&self&&self.Object===Object&&self,tt=X||Z||Function("return this")(),et=tt.Symbol;function rt(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var a=Array(o);++n-1;);return r}(n,o),function(t,e){for(var r=t.length;r--&&jt(e,t[r],0)>-1;);return r}(n,o)+1).join("")}var Ft=function(t){return!!nt(t)||null!=t&&""!==Mt(t)},Wt="[object Number]";function Lt(t){return function(t){return"number"==typeof t||ht(t)&&pt(t)==Wt}(t)&&t!=+t}var Jt="[object String]";function It(t){return"string"==typeof t||!nt(t)&&ht(t)&&pt(t)==Jt}var Ut=function(t){return!It(t)&&!Lt(parseFloat(t))},Dt=function(t){return""!==Mt(t)&&It(t)},Ht=function(t){return null!=t&&"boolean"==typeof t},Vt=function(t,e){return void 0===e&&(e=!0),void 0!==t&&""!==t&&""!==Mt(t)&&(!1===e||!0===e&&null!==t)},Bt=b,Yt=_,Kt=m,Gt=w,Qt=j,Xt=S,Zt="continue",te=function(t){switch(t){case"number":return Ut;case"string":return Dt;case"boolean":return Ht;default:return Vt}},ee=function(t,e){return void 0===e&&(e=""),!!nt(t)&&(""===e||""===Mt(e)||!(t.filter((function(t){return!te(e)(t)})).length>0))},re=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var e=t.replace("array.<","").replace(">","");return e.indexOf("|")?e.split("|"):[e]}return!1},ne=function(t,e){var r=t.arg;return e.length>1?!r.filter((function(t){return!(e.length>e.filter((function(e){return!te(e)(t)})).length)})).length:e.length>e.filter((function(t){return!ee(r,t)})).length};function oe(t,e){return function(r){return t(e(r))}}var ae=oe(Object.getPrototypeOf,Object),ie="[object Object]",ue=Function.prototype,ce=Object.prototype,fe=ue.toString,se=ce.hasOwnProperty,le=fe.call(Object);function pe(t){if(!ht(t)||pt(t)!=ie)return!1;var e=ae(t);if(null===e)return!0;var r=se.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&fe.call(r)==le}var he,ve=function(t,e,r){for(var n=-1,o=Object(t),a=r(t),i=a.length;i--;){var u=a[he?i:++n];if(!1===e(o[u],u,o))break}return t};var ge="[object Arguments]";function de(t){return ht(t)&&pt(t)==ge}var ye=Object.prototype,be=ye.hasOwnProperty,_e=ye.propertyIsEnumerable,me=de(function(){return arguments}())?de:function(t){return ht(t)&&be.call(t,"callee")&&!_e.call(t,"callee")};var we="object"==typeof exports&&exports&&!exports.nodeType&&exports,je=we&&"object"==typeof module&&module&&!module.nodeType&&module,Se=je&&je.exports===we?tt.Buffer:void 0,Oe=(Se?Se.isBuffer:void 0)||function(){return!1},ke=9007199254740991,Ee=/^(?:0|[1-9]\d*)$/;function $e(t,e){var r=typeof t;return!!(e=null==e?ke:e)&&("number"==r||"symbol"!=r&&Ee.test(t))&&t>-1&&t%1==0&&t-1&&t%1==0&&t<=Te}var Pe={};Pe["[object Float32Array]"]=Pe["[object Float64Array]"]=Pe["[object Int8Array]"]=Pe["[object Int16Array]"]=Pe["[object Int32Array]"]=Pe["[object Uint8Array]"]=Pe["[object Uint8ClampedArray]"]=Pe["[object Uint16Array]"]=Pe["[object Uint32Array]"]=!0,Pe["[object Arguments]"]=Pe["[object Array]"]=Pe["[object ArrayBuffer]"]=Pe["[object Boolean]"]=Pe["[object DataView]"]=Pe["[object Date]"]=Pe["[object Error]"]=Pe["[object Function]"]=Pe["[object Map]"]=Pe["[object Number]"]=Pe["[object Object]"]=Pe["[object RegExp]"]=Pe["[object Set]"]=Pe["[object String]"]=Pe["[object WeakMap]"]=!1;var ze,Ne="object"==typeof exports&&exports&&!exports.nodeType&&exports,Ce=Ne&&"object"==typeof module&&module&&!module.nodeType&&module,xe=Ce&&Ce.exports===Ne&&X.process,qe=function(){try{var t=Ce&&Ce.require&&Ce.require("util").types;return t||xe&&xe.binding&&xe.binding("util")}catch(t){}}(),Re=qe&&qe.isTypedArray,Me=Re?(ze=Re,function(t){return ze(t)}):function(t){return ht(t)&&Ae(t.length)&&!!Pe[pt(t)]},Fe=Object.prototype.hasOwnProperty;function We(t,e){var r=nt(t),n=!r&&me(t),o=!r&&!n&&Oe(t),a=!r&&!n&&!o&&Me(t),i=r||n||o||a,u=i?function(t,e){for(var r=-1,n=Array(t);++r-1},rr.prototype.set=function(t,e){var r=this.__data__,n=tr(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};var nr,or=tt["__core-js_shared__"],ar=(nr=/[^.]+$/.exec(or&&or.keys&&or.keys.IE_PROTO||""))?"Symbol(src)_1."+nr:"";var ir=Function.prototype.toString;function ur(t){if(null!=t){try{return ir.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var cr=/^\[object .+?Constructor\]$/,fr=Function.prototype,sr=Object.prototype,lr=fr.toString,pr=sr.hasOwnProperty,hr=RegExp("^"+lr.call(pr).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function vr(t){return!(!De(t)||function(t){return!!ar&&ar in t}(t))&&(Ke(t)?hr:cr).test(ur(t))}function gr(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return vr(r)?r:void 0}var dr=gr(tt,"Map"),yr=gr(Object,"create");var br="__lodash_hash_undefined__",_r=Object.prototype.hasOwnProperty;var mr=Object.prototype.hasOwnProperty;var wr="__lodash_hash_undefined__";function jr(t){var e=-1,r=null==t?0:t.length;for(this.clear();++eu))return!1;var f=a.get(t);if(f&&a.get(e))return f==e;var s=-1,l=!0,p=r&zr?new Tr:void 0;for(a.set(t,e),a.set(e,t);++se.type.filter((function(t){var e;return void 0===r||(!1!==(e=re(t))?!ne({arg:r},e):!te(t)(r))})).length)})).length}return!1},Xn=function(t,e){var r,n,o,a,i;switch(!0){case"object"===t:return o=(n=e).arg,a=n.param,i=[o],Array.isArray(a.keys)&&a.keys.length&&i.push(a.keys),!Reflect.apply(Qn,null,i);case"array"===t:return!ee(e.arg);case!1!==(r=re(t)):return!ne(e,r);default:return!te(t)(e.arg)}},Zn=function(t,e){return void 0!==t?t:!0===e.optional&&void 0!==e.defaultvalue?e.defaultvalue:null},to=function(t,e,r){var n;void 0===r&&(r=!1);var o=function(t,e){if(!ee(e))throw new D("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===e.length)return[];if(!ee(t))throw new D("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==e.length:return t.map((function(t,r){return{arg:t,index:r,param:e[r]}}));case!0===e[0].variable:var r=e[0].type;return t.map((function(t,n){return{arg:t,index:n,param:e[n]||{type:r,name:"_"}}}));case t.lengthe.length:var n=e.length,o=["any"];return t.map((function(t,r){var a=r>=n||!!e[r].optional,i=e[r]||{type:o,name:"_"+r};return{arg:a?Zn(t,i):t,index:r,param:i,optional:a}}));default:throw new D("Could not understand your arguments and parameter structure!",{args:t,params:e})}}(t,e),a=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var e=t.arg,r=t.param;return!!Ft(e)&&!(r.type.length>r.type.filter((function(e){return Xn(e,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(e){return Xn(e,t)})).length)}));return r?((n={})[p]=a,n[l]=o.map((function(t){return t.arg})),n):a},eo=function(){try{var t=gr(Object,"defineProperty");return t({},"",{}),t}catch(t){}}();function ro(t,e,r){"__proto__"==e&&eo?eo(t,e,{configurable:!0,enumerable:!0,value:r,writable:!0}):t[e]=r}function no(t,e,r){(void 0===r||Ze(t[e],r))&&(void 0!==r||e in t)||ro(t,e,r)}var oo="object"==typeof exports&&exports&&!exports.nodeType&&exports,ao=oo&&"object"==typeof module&&module&&!module.nodeType&&module,io=ao&&ao.exports===oo?tt.Buffer:void 0,uo=io?io.allocUnsafe:void 0;function co(t,e){var r,n,o=e?(r=t.buffer,n=new r.constructor(r.byteLength),new Cr(n).set(new Cr(r)),n):t.buffer;return new t.constructor(o,t.byteOffset,t.length)}var fo=Object.create,so=function(){function t(){}return function(e){if(!De(e))return{};if(fo)return fo(e);t.prototype=e;var r=new t;return t.prototype=void 0,r}}();function lo(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var po=Object.prototype.hasOwnProperty;function ho(t,e,r){var n=t[e];po.call(t,e)&&Ze(n,r)&&(void 0!==r||e in t)||ro(t,e,r)}var vo=Object.prototype.hasOwnProperty;function go(t){if(!De(t))return function(t){var e=[];if(null!=t)for(var r in Object(t))e.push(r);return e}(t);var e=Je(t),r=[];for(var n in t)("constructor"!=n||!e&&vo.call(t,n))&&r.push(n);return r}function yo(t){return Ge(t)?We(t,!0):go(t)}function bo(t){return function(t,e,r,n){var o=!r;r||(r={});for(var a=-1,i=e.length;++a0){if(++e>=Oo)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(So);function To(t,e){return $o(function(t,e,r){return e=jo(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,a=jo(n.length-e,0),i=Array(a);++o1?e[n-1]:void 0,a=n>2?e[2]:void 0;for(o=Ao.length>3&&"function"==typeof o?(n--,o):void 0,a&&function(t,e,r){if(!De(r))return!1;var n=typeof e;return!!("number"==n?Ge(r)&&$e(e,r.length):"string"==n&&e in r)&&Ze(r[e],t)}(e[0],e[1],a)&&(o=n<3?void 0:o,n=1),t=Object(t);++r0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return Reflect.apply(e,null,Xo(t))}),Reflect.apply(t,null,r))}};function na(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return t.then((function(t){return e(t)}))}),Reflect.apply(t,null,r))}}function oa(t,e,r,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,e)&&Object.defineProperty(t,e,{set:r,get:null===n?function(){return null}:n}),t}function aa(t,e){var r=Object.getOwnPropertyDescriptor(t,e);return void 0!==r&&r.value?r.value:r}function ia(t,e,r,n){void 0===n&&(n=!1);var o=aa(t,e);return!1===n&&void 0!==o?t:(Object.defineProperty(t,e,{value:r,writable:n}),t)}function ua(t){return!!Zo(t,"socket")&&t.socket}var ca=function(t){void 0===t&&(t=!1);var e=Date.now();return t?Math.floor(e/1e3):e},fa=function(t){var e;return(e={}).args=t,e};function sa(t,e,r){if(void 0===e&&(e=[]),void 0===r&&(r=!1),It(t)&&nt(e)){var n=fa(e);return!0===r?n:function(t,e){var r;return(r={})[t]=e,r[y]=[ca()],r}(t,n)}throw new s("[createQuery] expect resolverName to be string and args to be array!",{resolverName:t,args:e})}var la="__passed__";function pa(t,e){for(var r=[],n=arguments.length-2;n-- >0;)r[n]=arguments[n+2];r.push((function(t){return ia(t,O,ca())}));var o=Reflect.apply(ra,null,r);return function(r){return void 0===r&&(r={}),o(r,t,e)}}var ha=new WeakMap,va=new WeakMap;var ga=function(){this.__suspend__=null,this.queueStore=new Set},da={$suspend:{configurable:!0},$queues:{configurable:!0}};da.$suspend.set=function(t){var e=this;if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value!");var r=this.__suspend__;this.__suspend__=t,this.logger("($suspend)","Change from "+r+" --\x3e "+t),!0===r&&!1===t&&setTimeout((function(){e.release()}),1)},ga.prototype.$queue=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return!0===this.__suspend__&&(this.logger("($queue)","added to $queue",t),this.queueStore.add(t)),this.__suspend__},da.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},ga.prototype.release=function(){var t=this,e=this.queueStore.size;if(this.logger("(release)","Release was called "+e),e>0){var r=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",r),r.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(ga.prototype,da);var ya=function(t){function e(e){if("function"!=typeof e)throw new Error("Just die here the logger is not a function!");t.call(this,{logger:e})}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(e.prototype,r),e}(function(t){function e(e){void 0===e&&(e={}),t.call(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={$done:{configurable:!0}};return e.prototype.logger=function(){},e.prototype.$on=function(t,e,r){var n=this;void 0===r&&(r=null);this.validate(t,e);var o=this.takeFromStore(t);if(!1===o)return this.logger("($on)",t+" callback is not in lazy store"),this.addToNormalStore(t,"on",e,r);this.logger("($on)",t+" found in lazy store");var a=0;return o.forEach((function(o){var i=o[0],u=o[1],c=o[2];if(c&&"on"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);n.logger("($on)","call run on "+t),n.run(e,i,r||u),a+=n.addToNormalStore(t,"on",e,r||u)})),a},e.prototype.$once=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=this.takeFromStore(t);this.normalStore;if(!1===n)return this.logger("($once)",t+" not in the lazy store"),this.addToNormalStore(t,"once",e,r);this.logger("($once)",n);var o=Array.from(n)[0],a=o[0],i=o[1],u=o[2];if(u&&"once"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);this.logger("($once)","call run for "+t),this.run(e,a,r||i),this.$off(t)},e.prototype.$only=function(t,e,r){var n=this;void 0===r&&(r=null),this.validate(t,e);var o=!1,a=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger("($only)",t+" add to store"),o=this.addToNormalStore(t,"only",e,r)),!1!==a)&&(this.logger("($only)",t+" found data in lazy store to execute"),Array.from(a).forEach((function(o){var a=o[0],i=o[1],u=o[2];if(u&&"only"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);n.logger("($only)","call run for "+t),n.run(e,a,r||i)})));return o},e.prototype.$onlyOnce=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=!1,o=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger("($onlyOnce)",t+" add to store"),n=this.addToNormalStore(t,"onlyOnce",e,r)),!1!==o){this.logger("($onlyOnce)",o);var a=Array.from(o)[0],i=a[0],u=a[1],c=a[2];if(c&&"onlyOnce"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);this.logger("($onlyOnce)","call run for "+t),this.run(e,i,r||u),this.$off(t)}return n},e.prototype.$replace=function(t,e,r,n){if(void 0===r&&(r=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,e),Reflect.apply(o,this,[t,e,r])}throw new Error(n+" is not supported!")},e.prototype.$trigger=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,a=this.normalStore;if(this.logger("($trigger)","normalStore",a),a.has(t)){var i=this.$queue(t,e,r,n);if(this.logger("($trigger)",t,"found; add to queue: ",i),!0===i)return this.logger("($trigger)",t,"not executed. Exit now."),!1;for(var u=Array.from(a.get(t)),c=u.length,f=!1,s=0;s0;)n[o]=arguments[o+2];if(t.has(e)?(this.logger("(addToStore)",e+" existed"),r=t.get(e)):(this.logger("(addToStore)","create new Set for "+e),r=new Set),n.length>2)if(Array.isArray(n[0])){var a=n[2];this.checkTypeInLazyStore(e,a)||r.add(n)}else this.checkContentExist(n,r)||(this.logger("(addToStore)","insert new",n),r.add(n));else r.add(n);return t.set(e,r),[t,r.size]},e.prototype.checkContentExist=function(t,e){return!!Array.from(e).filter((function(e){return e[0]===t[0]})).length},e.prototype.checkTypeInStore=function(t,e){this.validateEvt(t,e);var r=this.$get(t,!0);return!1===r||!r.filter((function(t){var r=t[3];return e!==r})).length},e.prototype.checkTypeInLazyStore=function(t,e){this.validateEvt(t,e);var r=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",r),!!r&&!!Array.from(r).filter((function(t){return t[2]!==e})).length},e.prototype.addToNormalStore=function(t,e,r,n){if(void 0===n&&(n=null),this.logger("(addToNormalStore)",t,e,"try to add to normal store"),this.checkTypeInStore(t,e)){this.logger("(addToNormalStore)",e+" can add to "+t+" normal store");var o=this.hashFnToKey(r),a=[this.normalStore,t,o,r,n,e],i=Reflect.apply(this.addToStore,this,a),u=i[0],c=i[1];return this.normalStore=u,c}return!1},e.prototype.addToLazyStore=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(e),r];n&&o.push(n);var a=Reflect.apply(this.addToStore,this,o),i=a[0],u=a[1];return this.lazyStore=i,u},e.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},r.normalStore.set=function(t){ha.set(this,t)},r.normalStore.get=function(){return ha.get(this)},r.lazyStore.set=function(t){va.set(this,t)},r.lazyStore.get=function(){return va.get(this)},e.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,e){return(t=(t<<5)-t+e.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(e.prototype,r),e}(ga))),ba=function(t){var e=ua(t);if(!1!==e)return e;throw new i("Missing property in contract!")};function _a(t){var e,r,n=t.contract;return t.enableAuth?function(t,e){void 0===e&&(e=!1);var r=ua(t);if(!1===r){if(e)return t;throw new D("socket not found in contract!")}var n,o={},a=0;for(var i in r){var u=r[i],c=u.namespace;c&&(o[c]||(++a,o[c]={}),o[c][i]=u,n||u.public&&(n=c))}return{size:a,nspSet:o,publicNamespace:n}}(n):((r={})[z]=((e={})[h]=ba(n),e),r[N]=h,r)}var ma=function(t,e){return"ws"===e?t.replace("http://","ws://"):t},wa=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new s(t)}},ja=function(t,e){Xo(e).forEach((function(e){t.$off(ta(e,T))}))};function Sa(t,e,r){Zo(t,p)?r(t[p]):Zo(t,l)?e(t[l]):r({message:K,error:t})}function Oa(t,e,r,n,o){void 0===o&&(o=[]);var a=ta(e,T),i=n?W:x;return t.$trigger(a,[r,Xo(o)]),new Promise((function(n,o){t.$on(ta(e,r,i),(function(t){Sa(t,n,o)}))}))}var ka=function(t,e,r,n,o,a){return oa(t,"send",(function(t){var i=a?L:q;Ko(Xo(t),o.params,!0).then((function(o){if(!o[p]||!o[p].length)return Oa(e,r,n,a,t);e.$call(ta(r,n,i),[new s(n,o[p])])})).catch((function(t){e.$call(ta(r,n,i),[new s(n,t)])}))}),(function(){return function(){for(var t=[],i=arguments.length;i--;)t[i]=arguments[i];return Ko(t,o.params,!0).then((function(t){return Oa(e,r,n,a,t)})).catch(V)}}))};function Ea(t,e,r,n,o){return[ia(t,G,(function(t,o){if(Yo(t)&&ea(o))switch(t){case W:e.$on(ta(r,n,x),(function(t){Sa(t,o,(function(t){e.$trigger(ta(r,n,q),t)}))}));break;case F:e.$only(ta(r,n,C),(function(t){Sa(t,o,(function(t){e.$trigger(ta(r,n,q),t)}))}));break;case J:e.$only(ta(r,n,q),o);break;default:e.$trigger(ta(r,n,q),new D(n,"Unknown event name "+t+"!"))}})),e,r,n,o]}var $a=function(t,e,r,n,o,a){return[ia(t,"myNamespace",r),e,r,n,o,a]},Ta=function(t,e,r,n,o,a){return[oa(t,x,(function(t){ea(t)&&e.$on(ta(r,n,x),(function(o){Sa(o,t,(function(t){e.$trigger(ta(r,n,q),t)}))}))})),e,r,n,o,a]},Aa=function(t,e,r,n,o,a){return[oa(t,C,(function(t){if(ea(t)){e.$only(ta(r,n,C),(function(o){Sa(o,t,(function(t){e.$trigger(ta(r,n,q),t)}))}))}})),e,r,n,o,a]},Pa=function(t,e,r,n,o,a){return[oa(t,q,(function(t){ea(t)&&e.$only(ta(r,n,q),t)})),e,r,n,o,a]};function za(t,e,r,n,o,a){var i=[$a];a?i.push(Ea):i.push(Ta,Aa,Pa),i.push(ka);var u=Reflect.apply(ra,null,i);return Reflect.apply(u,null,[n,o,t,e,r,a])}function Na(t,e,r,n,o){return function(){for(var a=[],i=arguments.length;i--;)a[i]=arguments[i];return Ko(a,n.params,!0).then((function(n){return Oa(t,e,r,o,n)})).catch(V)}}var Ca,xa,qa=function(t,e,r){return[ia(t,r.loginHandlerName,(function(t){if(t&&Yo(t))return e.$trigger(E,[t]);throw new s(r.loginHandlerName,"Unexpected token "+t)})),e,r]},Ra=function(t,e,r){return ia(t,r.logoutHandlerName,(function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];e.$trigger($,t)}))};function Ma(t,e,r){var n={},o=e.nspSet,a=t.useCallbackStyle;for(var i in o){var u=o[i];for(var c in u){var f=u[c];n=ia(n,c,za(i,c,f,Na(r,i,c,f,a),r,a))}}return n.devHelpers={getNsp:function(){return Object.keys(o)},getVer:function(){return t.version||"NOT SET"}},Promise.resolve(n)}function Fa(t,e,r){var n=e.nspSet,o=t.useCallbackStyle,a=t.enableAuth,i=[Ma];return o?i.push((function(t){return function(t,e,r,n){return ia(t,G,(function(t,n){if(Yo(t)&&ea(n))switch(t){case L:for(var o in r)e.$on(ta(o,L),n);break;case I:e.$only(I,n);break;case J:e.$on(J,n);break;default:e.$trigger(L,new D(G,"Unknown event name "+t+"!"))}}))}(t,r,n)})):(i.push((function(t){return function(t,e,r){return oa(t,q,(function(t){if(ea(t))for(var n in r)e.$on(ta(n,q),t)}))}(t,r,n)}),(function(t){return function(t,e,r){return oa(t,R,(function(t){ea(t)&&e.$on(R,t)}))}(t,r)})),a&&i.push((function(e){return function(t,e,r){return r.enableAuth?oa(t,M,(function(t){ea(t)&&e.$only(M,t)})):t}(e,r,t)}))),a&&i.push((function(e){return function(t,e,r){return r.enableAuth?ra(qa,Ra)(t,e,r):t}(e,r,t)})),Reflect.apply(na,null,i)(t,e,r)}var Wa=["roundtip","handshake"],La={useCallbackStyle:Go(!1,["boolean"]),loginHandlerName:Go("login",["string"]),logoutHandlerName:Go("logout",["string"]),loginMethod:Go("handshake",["string"],(Ca={},Ca[m]=Wa,Ca)),useJwt:Go(!0,["boolean","string"]),authStrKey:Go(null,["string"]),hostname:Go(!1,["string"]),namespace:Go(h,["string"]),wsOptions:Go({},["object"]),contract:Go({},["object"],(xa={},xa[j]=function(t){return!!function(t){return pe(t)&&(Zo(t,v)||Zo(t,g)||Zo(t,d))}(t)&&t},xa)),enableAuth:Go(!1,["boolean"]),token:Go(!1,["string"])},Ja={eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:""};function Ia(t,e,r){var n=Object.assign(Ja,r);return function(t,e){for(var r=[],n=arguments.length-2;n-- >0;)r[n]=arguments[n+2];return function(n){var o;if(void 0===n&&(n={}),aa(n,O)){var a=1;return n[la]&&(a=++n[la],delete n[la]),Promise.resolve(Object.assign(((o={})[la]=a,o),n,e))}var i=Reflect.apply(pa,null,[t,e].concat(r));return Promise.resolve(i(n))}}(Object.assign(La,e),n,Qo)(t)}var Ua=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];Reflect.apply(console.info,console,["[jsonql-ws-client-core]"].concat(t))},Da=function(t){var e=t.log,r=t.eventEmitter;return e("CHECKED_KEY",t[O]),r?(e("eventEmitter is:",r.name),r):(e("Create a new Event Emitter"),new ya(t.log))},Ha=function(t){var e=t.log;return e&&"function"==typeof e||(t.log=Ua),t.log("--- wsClientCore config opts ---",t),t};function Va(t,e,r){return void 0===e&&(e={}),void 0===r&&(r={}),function(n){return void 0===n&&(n={}),function(t,e,r){return Ia(t,e,r).then((function(t){return t.hostname||(t.hostname=wa()),t.wssPath=ma([t.hostname,t.namespace].join("/"),t.serverType),t}))}(n,e,r).then(Ha).then((function(t){return{opts:t,nspMap:_a(t),ee:Da(t)}})).then((function(e){var r=e.opts,n=e.nspMap,o=e.ee;return t(r,n,o)})).then((function(t){return Fa(t.opts,t.nspMap,t.ee)})).catch((function(t){console.error("jsonql-ws-core-client init error",t)}))}}var Ba=null;"undefined"!=typeof WebSocket?Ba=WebSocket:"undefined"!=typeof MozWebSocket?Ba=MozWebSocket:void 0!==Q?Ba=Q.WebSocket||Q.MozWebSocket:"undefined"!=typeof window?Ba=window.WebSocket||window.MozWebSocket:"undefined"!=typeof self&&(Ba=self.WebSocket||self.MozWebSocket);var Ya=function(t){var e=t.toLowerCase();return e.indexOf("http")>-1?e.indexOf("https")>-1?e.replace("https","wss"):e.replace("http","ws"):e};function Ka(t,e){return void 0===e&&(e=!1),!1===e?function(e){return new t(Ya(e))}:function(e,r){var n=Ya(e),o=r&&"string"==typeof r?n+"?"+U+"="+r:n;try{return new t(o)}catch(t){return console.error("WebSocket Connection Error",t),!1}}}function Ga(t,e){var r=e.hostname,n=e.wssPath,o=e.wsOptions;return(0,e.nspClient)(t?[r,t].join("/"):n,o)}var Qa=function(t,e,r){var n=r.useCallbackStyle,o=r.log,a=n?L:q,i=n?W:x;e.$only(ta(t,Y),(function(r,n){o("[notLoginHandler] hijack the ws call",t,r,n);var u={message:"NOT LOGIN"};e.$call(ta(t,r,a),[u]),e.$call(ta(t,r,i),[{error:u}])}))},Xa=function(t){return t.length>1&&t[0]};function Za(t,e,r,n,o,a){var i=Xa(o),u=!1,c=t.log;o.forEach((function(o){if(u=i===o,a[o]){c("[call bindWsHandler]",u,o);var f=[o,a[o],r,u,t];if(t.serverType===B){var s=e.nspSet;f.push(s[o])}Reflect.apply(n,null,f)}else Qa(o,r,t)})),r.$on($,(function(){c("LOGOUT_EVENT_NAME"),function(t,e,r,n){void 0===n&&(n={});var o=n.useCallbackStyle?L:q;e.forEach((function(e){t.$call(ta(e,o),[{message:r,namespace:e}])}))}(r,o,$),o.forEach((function(e){ja(r,e),a[e]=!1,Qa(e,r,t)}))}))}var ti=["__reply__","__event__","__data__"],ei=function(t){var e,r=t.data;if(!1!==(e=function(t){var e=t.data;return!!e&&(ti.filter((function(t){return Zo(e,t)})).length===ti.length&&e)}(Yo(r)?JSON.parse(r):r)))return{resolverName:e.__event__,data:e.__data__,type:e.__reply__};throw new D("payload can not be decoded",t)},ri=function(t,e,r,n,o){var a=[e];r&&a.push(r),a.push(o);var i=Reflect.apply(ta,null,a),u=n.data||n;t.$trigger(i,[u])};function ni(t,e,r,n,o){var a=o.useCallbackStyle,i=o.log;i("wsMainHandler log test");var u=a?J:R,c=a?I:M,f=a?F:C,s=a?W:x,l=a?L:q;e.onopen=function(){i("ws.onopen listened"),r.$call(u,t),n&&(i("isPrivate and fire the "+c),r.$call(c,t)),r.$only(ta(t,T),(function(t,r){i("calling server",t,r),e.send(function(t,e,r){return void 0===e&&(e=[]),void 0===r&&(r=!1),JSON.stringify(sa(t,e,r))}(t,r))}))},e.onmessage=function(e){try{var n=ei(e),o=n.resolverName,a=n.type;switch(i("Hear from server",a,n),a){case T:var u=ta(t,o,f),c=r.$trigger(u,[n]);i("EMIT_REPLY_TYPE",u,c);break;case A:var p=ta(t,o,s);r.$trigger(p,[n]);break;case P:i("ERROR_TYPE"),ri(r,t,o,n,l);break;default:i("Unhandled event!",n),ri(r,t,o,n,l)}}catch(e){console.error("ws.onmessage error",e),ri(r,t,!1,e,l)}},e.onclose=function(){i("ws.onclose callback")},r.$on($,(function(){try{i("terminate ws connection"),e.terminate()}catch(t){console.error("ws.terminate error",t)}}))}var oi=function(t,e,r){var n,o=e.nspSet,a=e.publicNamespace,i=!1,u=[],c={};if(t.enableAuth)i=!0,c=(u=function(t,e){var r=[];for(var n in t)n===e?r[1]=n:r[0]=n;return r}(o,a)).map((function(e,n){var o,a,i;return 0===n?r?(t.token=r,(o={})[e]=function(t,e){var r=e.hostname,n=e.wssPath,o=e.token,a=e.wsOptions,i=e.nspAuthClient,u=t?[r,t].join("/"):n;if(o&&"string"!=typeof o)throw new Error("Expect token to be string, but got "+o);return i(u,o,a)}(e,t),o):((a={})[e]=!1,a):((i={})[e]=Ga(e,t),i)})).reduce((function(t,e){return Object.assign(t,e)}),{});else{var f=(n=o,Object.keys(n)[0]);u.push(f),c[f]=Ga(!1,t)}return{nsps:c,namespaces:u,login:i}};var ai=function(t){var e=Ka(t),r=Ka(t,!0);return function(t,n,o){t.nspClient=e,t.nspAuthClient=r;var a=t.log;return a&&"function"==typeof a&&(a("@jsonql/ws ee",o.name),a("@jsonql/ws createClientResolver",t)),function(t,e,r){var n=[t,e,r,ni],o=t.token,a=t.log,i=oi(t,e,o),u=i.nsps,c=i.namespaces,f=i.login;return Reflect.apply(Za,null,n.concat([c,u])),f&&r.$only(E,(function(o){a("createClient LOGIN_EVENT_NAME"),ja(r,c);var i=oi(t,e,o);Reflect.apply(Za,null,n.concat([i.namespaces,i.nsps]))})),{opts:t,nspMap:e,ee:r}}(t,n,o)}}(Ba),ii={version:"version: 1.0.11 module: umd",serverType:"ws"},ui={};return function(t,e){return void 0===t&&(t={}),void 0===e&&(e={}),Va(ai,ui,Object.assign(ii,e))(t)}})); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).jsonqlWsClient=e()}(this,(function(){"use strict";var t=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 406},r.name.get=function(){return"Jsonql406Error"},Object.defineProperties(e,r),e}(Error),e=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"Jsonql500Error"},Object.defineProperties(e,r),e}(Error),r=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 403},r.name.get=function(){return"JsonqlForbiddenError"},Object.defineProperties(e,r),e}(Error),n=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlAuthorisationError"},Object.defineProperties(e,r),e}(Error),o=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlContractAuthError"},Object.defineProperties(e,r),e}(Error),a=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"JsonqlResolverAppError"},Object.defineProperties(e,r),e}(Error),i=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 404},r.name.get=function(){return"JsonqlResolverNotFoundError"},Object.defineProperties(e,r),e}(Error),u=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlEnumError"},Object.defineProperties(e,r),e}(Error),c=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlTypeError"},Object.defineProperties(e,r),e}(Error),s=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlCheckerError"},Object.defineProperties(e,r),e}(Error),f=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(e,r),e}(Error),l=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0},statusCode:{configurable:!0}};return r.name.get=function(){return"JsonqlError"},r.statusCode.get=function(){return-1},Object.defineProperties(e,r),e}(Error),p=function(t){function e(r,n){t.call(this,n),this.statusCode=r,this.className=e.name}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlServerError"},Object.defineProperties(e,r),e}(Error);function h(h){if(Array.isArray(h))throw new f("",h);var v=h.message||"No message",g=h.detail||h;switch(!0){case h instanceof t:throw new t(v,g);case h instanceof e:throw new e(v,g);case h instanceof r:throw new r(v,g);case h instanceof n:throw new n(v,g);case h instanceof o:throw new o(v,g);case h instanceof a:throw new a(v,g);case h instanceof i:throw new i(v,g);case h instanceof u:throw new u(v,g);case h instanceof c:throw new c(v,g);case h instanceof s:throw new s(v,g);case h instanceof f:throw new f(v,g);case h instanceof p:throw new p(v,g);default:throw new l(v,g)}}var v="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},g="object"==typeof v&&v&&v.Object===Object&&v,d="object"==typeof self&&self&&self.Object===Object&&self,y=g||d||Function("return this")(),b=y.Symbol;function _(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var a=Array(o);++n-1;);return r}(n,o),function(t,e){for(var r=t.length;r--&&R(e,t[r],0)>-1;);return r}(n,o)+1).join("")}var Q=function(t){return!!m(t)||null!=t&&""!==G(t)};function X(t){return function(t){return"number"==typeof t||T(t)&&"[object Number]"==$(t)}(t)&&t!=+t}function Z(t){return"string"==typeof t||!m(t)&&T(t)&&"[object String]"==$(t)}var tt=function(t){return!Z(t)&&!X(parseFloat(t))},et=function(t){return""!==G(t)&&Z(t)},rt=function(t){return null!=t&&"boolean"==typeof t},nt=function(t,e){return void 0===e&&(e=!0),void 0!==t&&""!==t&&""!==G(t)&&(!1===e||!0===e&&null!==t)},ot=function(t){switch(t){case"number":return tt;case"string":return et;case"boolean":return rt;default:return nt}},at=function(t,e){return void 0===e&&(e=""),!!m(t)&&(""===e||""===G(e)||!(t.filter((function(t){return!ot(e)(t)})).length>0))},it=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var e=t.replace("array.<","").replace(">","");return e.indexOf("|")?e.split("|"):[e]}return!1},ut=function(t,e){var r=t.arg;return e.length>1?!r.filter((function(t){return!(e.length>e.filter((function(e){return!ot(e)(t)})).length)})).length:e.length>e.filter((function(t){return!at(r,t)})).length};function ct(t,e){return function(r){return t(e(r))}}var st=ct(Object.getPrototypeOf,Object),ft=Function.prototype,lt=Object.prototype,pt=ft.toString,ht=lt.hasOwnProperty,vt=pt.call(Object);function gt(t){if(!T(t)||"[object Object]"!=$(t))return!1;var e=st(t);if(null===e)return!0;var r=ht.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&pt.call(r)==vt}var dt,yt=function(t,e,r){for(var n=-1,o=Object(t),a=r(t),i=a.length;i--;){var u=a[dt?i:++n];if(!1===e(o[u],u,o))break}return t};function bt(t){return T(t)&&"[object Arguments]"==$(t)}var _t=Object.prototype,mt=_t.hasOwnProperty,wt=_t.propertyIsEnumerable,jt=bt(function(){return arguments}())?bt:function(t){return T(t)&&mt.call(t,"callee")&&!wt.call(t,"callee")};var Ot="object"==typeof exports&&exports&&!exports.nodeType&&exports,St=Ot&&"object"==typeof module&&module&&!module.nodeType&&module,kt=St&&St.exports===Ot?y.Buffer:void 0,Et=(kt?kt.isBuffer:void 0)||function(){return!1},$t=/^(?:0|[1-9]\d*)$/;function Tt(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&$t.test(t))&&t>-1&&t%1==0&&t-1&&t%1==0&&t<=9007199254740991}var Pt={};Pt["[object Float32Array]"]=Pt["[object Float64Array]"]=Pt["[object Int8Array]"]=Pt["[object Int16Array]"]=Pt["[object Int32Array]"]=Pt["[object Uint8Array]"]=Pt["[object Uint8ClampedArray]"]=Pt["[object Uint16Array]"]=Pt["[object Uint32Array]"]=!0,Pt["[object Arguments]"]=Pt["[object Array]"]=Pt["[object ArrayBuffer]"]=Pt["[object Boolean]"]=Pt["[object DataView]"]=Pt["[object Date]"]=Pt["[object Error]"]=Pt["[object Function]"]=Pt["[object Map]"]=Pt["[object Number]"]=Pt["[object Object]"]=Pt["[object RegExp]"]=Pt["[object Set]"]=Pt["[object String]"]=Pt["[object WeakMap]"]=!1;var zt,Nt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Ct=Nt&&"object"==typeof module&&module&&!module.nodeType&&module,xt=Ct&&Ct.exports===Nt&&g.process,Rt=function(){try{var t=Ct&&Ct.require&&Ct.require("util").types;return t||xt&&xt.binding&&xt.binding("util")}catch(t){}}(),qt=Rt&&Rt.isTypedArray,Mt=qt?(zt=qt,function(t){return zt(t)}):function(t){return T(t)&&At(t.length)&&!!Pt[$(t)]},Ft=Object.prototype.hasOwnProperty;function Lt(t,e){var r=m(t),n=!r&&jt(t),o=!r&&!n&&Et(t),a=!r&&!n&&!o&&Mt(t),i=r||n||o||a,u=i?function(t,e){for(var r=-1,n=Array(t);++r-1},Xt.prototype.set=function(t,e){var r=this.__data__,n=Gt(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};var Zt,te=y["__core-js_shared__"],ee=(Zt=/[^.]+$/.exec(te&&te.keys&&te.keys.IE_PROTO||""))?"Symbol(src)_1."+Zt:"";var re=Function.prototype.toString;function ne(t){if(null!=t){try{return re.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var oe=/^\[object .+?Constructor\]$/,ae=Function.prototype,ie=Object.prototype,ue=ae.toString,ce=ie.hasOwnProperty,se=RegExp("^"+ue.call(ce).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function fe(t){return!(!Dt(t)||function(t){return!!ee&&ee in t}(t))&&(Ht(t)?se:oe).test(ne(t))}function le(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return fe(r)?r:void 0}var pe=le(y,"Map"),he=le(Object,"create");var ve=Object.prototype.hasOwnProperty;var ge=Object.prototype.hasOwnProperty;function de(t){var e=-1,r=null==t?0:t.length;for(this.clear();++eu))return!1;var s=a.get(t);if(s&&a.get(e))return s==e;var f=-1,l=!0,p=2&r?new me:void 0;for(a.set(t,e),a.set(e,t);++fe.type.filter((function(t){var e;return void 0===r||(!1!==(e=it(t))?!ut({arg:r},e):!ot(t)(r))})).length)})).length}return!1},dr=function(t,e){var r,n,o,a,i;switch(!0){case"object"===t:return o=(n=e).arg,a=n.param,i=[o],Array.isArray(a.keys)&&a.keys.length&&i.push(a.keys),!Reflect.apply(gr,null,i);case"array"===t:return!at(e.arg);case!1!==(r=it(t)):return!ut(e,r);default:return!ot(t)(e.arg)}},yr=function(t,e){return void 0!==t?t:!0===e.optional&&void 0!==e.defaultvalue?e.defaultvalue:null},br=function(t,e,r){var n;void 0===r&&(r=!1);var o=function(t,e){if(!at(e))throw new l("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===e.length)return[];if(!at(t))throw new l("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==e.length:return t.map((function(t,r){return{arg:t,index:r,param:e[r]}}));case!0===e[0].variable:var r=e[0].type;return t.map((function(t,n){return{arg:t,index:n,param:e[n]||{type:r,name:"_"}}}));case t.lengthe.length:var n=e.length,o=["any"];return t.map((function(t,r){var a=r>=n||!!e[r].optional,i=e[r]||{type:o,name:"_"+r};return{arg:a?yr(t,i):t,index:r,param:i,optional:a}}));default:throw new l("Could not understand your arguments and parameter structure!",{args:t,params:e})}}(t,e),a=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var e=t.arg,r=t.param;return!!Q(e)&&!(r.type.length>r.type.filter((function(e){return dr(e,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(e){return dr(e,t)})).length)}));return r?((n={}).error=a,n.data=o.map((function(t){return t.arg})),n):a},_r=function(){try{var t=le(Object,"defineProperty");return t({},"",{}),t}catch(t){}}();function mr(t,e,r){"__proto__"==e&&_r?_r(t,e,{configurable:!0,enumerable:!0,value:r,writable:!0}):t[e]=r}function wr(t,e,r){(void 0===r||Kt(t[e],r))&&(void 0!==r||e in t)||mr(t,e,r)}var jr="object"==typeof exports&&exports&&!exports.nodeType&&exports,Or=jr&&"object"==typeof module&&module&&!module.nodeType&&module,Sr=Or&&Or.exports===jr?y.Buffer:void 0,kr=Sr?Sr.allocUnsafe:void 0;function Er(t,e){var r,n,o=e?(r=t.buffer,n=new r.constructor(r.byteLength),new Oe(n).set(new Oe(r)),n):t.buffer;return new t.constructor(o,t.byteOffset,t.length)}var $r=Object.create,Tr=function(){function t(){}return function(e){if(!Dt(e))return{};if($r)return $r(e);t.prototype=e;var r=new t;return t.prototype=void 0,r}}();function Ar(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var Pr=Object.prototype.hasOwnProperty;function zr(t,e,r){var n=t[e];Pr.call(t,e)&&Kt(n,r)&&(void 0!==r||e in t)||mr(t,e,r)}var Nr=Object.prototype.hasOwnProperty;function Cr(t){if(!Dt(t))return function(t){var e=[];if(null!=t)for(var r in Object(t))e.push(r);return e}(t);var e=Jt(t),r=[];for(var n in t)("constructor"!=n||!e&&Nr.call(t,n))&&r.push(n);return r}function xr(t){return Vt(t)?Lt(t,!0):Cr(t)}function Rr(t){return function(t,e,r,n){var o=!r;r||(r={});for(var a=-1,i=e.length;++a0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(Wr);function Ur(t,e){return Ir(function(t,e,r){return e=Lr(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,a=Lr(n.length-e,0),i=Array(a);++o1?e[n-1]:void 0,a=n>2?e[2]:void 0;for(o=Dr.length>3&&"function"==typeof o?(n--,o):void 0,a&&function(t,e,r){if(!Dt(r))return!1;var n=typeof e;return!!("number"==n?Vt(r)&&Tt(e,r.length):"string"==n&&e in r)&&Kt(r[e],t)}(e[0],e[1],a)&&(o=n<3?void 0:o,n=1),t=Object(t);++r0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return Reflect.apply(e,null,sn(t))}),Reflect.apply(t,null,r))}};function vn(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return t.then((function(t){return e(t)}))}),Reflect.apply(t,null,r))}}function gn(t,e,r,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,e)&&Object.defineProperty(t,e,{set:r,get:null===n?function(){return null}:n}),t}function dn(t,e,r,n){void 0===n&&(n=!1);var o=function(t,e){var r=Object.getOwnPropertyDescriptor(t,e);return void 0!==r&&r.value?r.value:r}(t,e);return!1===n&&void 0!==o||Object.defineProperty(t,e,{value:r,writable:n}),t}function yn(t){return!!fn(t,"socket")&&t.socket}var bn=function(t){void 0===t&&(t=!1);var e=Date.now();return t?Math.floor(e/1e3):e};function _n(t,e,r){if(void 0===e&&(e=[]),void 0===r&&(r=!1),Z(t)&&m(e)){var n=function(t){var e;return(e={}).args=t,e}(e);return!0===r?n:function(t,e){var r;return(r={})[t]=e,r.TS=[bn()],r}(t,n)}throw new f("[createQuery] expect resolverName to be string and args to be array!",{resolverName:t,args:e})}var mn=new WeakMap,wn=new WeakMap;var jn=function(){this.__suspend__=null,this.queueStore=new Set},On={$suspend:{configurable:!0},$queues:{configurable:!0}};On.$suspend.set=function(t){var e=this;if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value!");var r=this.__suspend__;this.__suspend__=t,this.logger("($suspend)","Change from "+r+" --\x3e "+t),!0===r&&!1===t&&setTimeout((function(){e.release()}),1)},jn.prototype.$queue=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return!0===this.__suspend__&&(this.logger("($queue)","added to $queue",t),this.queueStore.add(t)),this.__suspend__},On.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},jn.prototype.release=function(){var t=this,e=this.queueStore.size;if(this.logger("(release)","Release was called "+e),e>0){var r=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",r),r.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(jn.prototype,On);var Sn=function(t){function e(e){if("function"!=typeof e)throw new Error("Just die here the logger is not a function!");t.call(this,{logger:e})}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(e.prototype,r),e}(function(t){function e(e){void 0===e&&(e={}),t.call(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={$done:{configurable:!0}};return e.prototype.logger=function(){},e.prototype.$on=function(t,e,r){var n=this;void 0===r&&(r=null);this.validate(t,e);var o=this.takeFromStore(t);if(!1===o)return this.logger("($on)",t+" callback is not in lazy store"),this.addToNormalStore(t,"on",e,r);this.logger("($on)",t+" found in lazy store");var a=0;return o.forEach((function(o){var i=o[0],u=o[1],c=o[2];if(c&&"on"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);n.logger("($on)","call run on "+t),n.run(e,i,r||u),a+=n.addToNormalStore(t,"on",e,r||u)})),a},e.prototype.$once=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=this.takeFromStore(t);this.normalStore;if(!1===n)return this.logger("($once)",t+" not in the lazy store"),this.addToNormalStore(t,"once",e,r);this.logger("($once)",n);var o=Array.from(n)[0],a=o[0],i=o[1],u=o[2];if(u&&"once"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);this.logger("($once)","call run for "+t),this.run(e,a,r||i),this.$off(t)},e.prototype.$only=function(t,e,r){var n=this;void 0===r&&(r=null),this.validate(t,e);var o=!1,a=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger("($only)",t+" add to store"),o=this.addToNormalStore(t,"only",e,r)),!1!==a)&&(this.logger("($only)",t+" found data in lazy store to execute"),Array.from(a).forEach((function(o){var a=o[0],i=o[1],u=o[2];if(u&&"only"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);n.logger("($only)","call run for "+t),n.run(e,a,r||i)})));return o},e.prototype.$onlyOnce=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=!1,o=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger("($onlyOnce)",t+" add to store"),n=this.addToNormalStore(t,"onlyOnce",e,r)),!1!==o){this.logger("($onlyOnce)",o);var a=Array.from(o)[0],i=a[0],u=a[1],c=a[2];if(c&&"onlyOnce"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);this.logger("($onlyOnce)","call run for "+t),this.run(e,i,r||u),this.$off(t)}return n},e.prototype.$replace=function(t,e,r,n){if(void 0===r&&(r=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,e),Reflect.apply(o,this,[t,e,r])}throw new Error(n+" is not supported!")},e.prototype.$trigger=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,a=this.normalStore;if(this.logger("($trigger)","normalStore",a),a.has(t)){var i=this.$queue(t,e,r,n);if(this.logger("($trigger)",t,"found; add to queue: ",i),!0===i)return this.logger("($trigger)",t,"not executed. Exit now."),!1;for(var u=Array.from(a.get(t)),c=u.length,s=!1,f=0;f0;)n[o]=arguments[o+2];if(t.has(e)?(this.logger("(addToStore)",e+" existed"),r=t.get(e)):(this.logger("(addToStore)","create new Set for "+e),r=new Set),n.length>2)if(Array.isArray(n[0])){var a=n[2];this.checkTypeInLazyStore(e,a)||r.add(n)}else this.checkContentExist(n,r)||(this.logger("(addToStore)","insert new",n),r.add(n));else r.add(n);return t.set(e,r),[t,r.size]},e.prototype.checkContentExist=function(t,e){return!!Array.from(e).filter((function(e){return e[0]===t[0]})).length},e.prototype.checkTypeInStore=function(t,e){this.validateEvt(t,e);var r=this.$get(t,!0);return!1===r||!r.filter((function(t){var r=t[3];return e!==r})).length},e.prototype.checkTypeInLazyStore=function(t,e){this.validateEvt(t,e);var r=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",r),!!r&&!!Array.from(r).filter((function(t){return t[2]!==e})).length},e.prototype.addToNormalStore=function(t,e,r,n){if(void 0===n&&(n=null),this.logger("(addToNormalStore)",t,e,"try to add to normal store"),this.checkTypeInStore(t,e)){this.logger("(addToNormalStore)",e+" can add to "+t+" normal store");var o=this.hashFnToKey(r),a=[this.normalStore,t,o,r,n,e],i=Reflect.apply(this.addToStore,this,a),u=i[0],c=i[1];return this.normalStore=u,c}return!1},e.prototype.addToLazyStore=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(e),r];n&&o.push(n);var a=Reflect.apply(this.addToStore,this,o),i=a[0],u=a[1];return this.lazyStore=i,u},e.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},r.normalStore.set=function(t){mn.set(this,t)},r.normalStore.get=function(){return mn.get(this)},r.lazyStore.set=function(t){wn.set(this,t)},r.lazyStore.get=function(){return wn.get(this)},e.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,e){return(t=(t<<5)-t+e.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(e.prototype,r),e}(jn)));function kn(t){var e,r,n=t.contract;return t.enableAuth?function(t,e){void 0===e&&(e=!1);var r=yn(t);if(!1===r){if(e)return t;throw new l("socket not found in contract!")}var n,o={},a=0;for(var i in r){var u=r[i],c=u.namespace;c&&(o[c]||(++a,o[c]={}),o[c][i]=u,n||u.public&&(n=c))}return{size:a,nspSet:o,publicNamespace:n}}(n):((r={}).nspSet=((e={}).jsonql=function(t){var e=yn(t);if(!1!==e)return e;throw new i("Missing property in contract!")}(n),e),r.publicNamespace="jsonql",r)}var En=function(t,e){sn(e).forEach((function(e){t.$off(ln(e,"emit"))}))};function $n(t,e,r){fn(t,"error")?r(t.error):fn(t,"data")?e(t.data):r({message:"UKNNOWN RESULT!",error:t})}function Tn(t,e,r,n,o){void 0===o&&(o=[]);var a=ln(e,"emit"),i=n?"result":"onResult";return t.$trigger(a,[r,sn(o)]),new Promise((function(n,o){t.$on(ln(e,r,i),(function(t){$n(t,n,o)}))}))}var An=function(t,e,r,n,o,a){return gn(t,"send",(function(t){var i=a?"error":"onError";an(sn(t),o.params,!0).then((function(o){if(!o.error||!o.error.length)return Tn(e,r,n,a,t);e.$call(ln(r,n,i),[new f(n,o.error)])})).catch((function(t){e.$call(ln(r,n,i),[new f(n,t)])}))}),(function(){return function(){for(var t=[],i=arguments.length;i--;)t[i]=arguments[i];return an(t,o.params,!0).then((function(t){return Tn(e,r,n,a,t)})).catch(h)}}))};function Pn(t,e,r,n,o){return[dn(t,"on",(function(t,o){if(on(t)&&pn(o))switch(t){case"result":e.$on(ln(r,n,"onResult"),(function(t){$n(t,o,(function(t){e.$trigger(ln(r,n,"onError"),t)}))}));break;case"message":e.$only(ln(r,n,"onMessage"),(function(t){$n(t,o,(function(t){e.$trigger(ln(r,n,"onError"),t)}))}));break;case"ready":e.$only(ln(r,n,"onError"),o);break;default:e.$trigger(ln(r,n,"onError"),new l(n,"Unknown event name "+t+"!"))}})),e,r,n,o]}var zn=function(t,e,r,n,o,a){return[dn(t,"myNamespace",r),e,r,n,o,a]},Nn=function(t,e,r,n,o,a){return[gn(t,"onResult",(function(t){pn(t)&&e.$on(ln(r,n,"onResult"),(function(o){$n(o,t,(function(t){e.$trigger(ln(r,n,"onError"),t)}))}))})),e,r,n,o,a]},Cn=function(t,e,r,n,o,a){return[gn(t,"onMessage",(function(t){if(pn(t)){e.$only(ln(r,n,"onMessage"),(function(o){$n(o,t,(function(t){e.$trigger(ln(r,n,"onError"),t)}))}))}})),e,r,n,o,a]},xn=function(t,e,r,n,o,a){return[gn(t,"onError",(function(t){pn(t)&&e.$only(ln(r,n,"onError"),t)})),e,r,n,o,a]};function Rn(t,e,r,n,o,a){var i=[zn];a?i.push(Pn):i.push(Nn,Cn,xn),i.push(An);var u=Reflect.apply(hn,null,i);return Reflect.apply(u,null,[n,o,t,e,r,a])}function qn(t,e,r,n,o){return function(){for(var a=[],i=arguments.length;i--;)a[i]=arguments[i];return an(a,n.params,!0).then((function(n){return Tn(t,e,r,o,n)})).catch(h)}}var Mn,Fn,Ln=function(t,e,r){return[dn(t,r.loginHandlerName,(function(t){if(t&&on(t))return e.$trigger("__login__",[t]);throw new f(r.loginHandlerName,"Unexpected token "+t)})),e,r]},Wn=function(t,e,r){return dn(t,r.logoutHandlerName,(function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];e.$trigger("__logout__",t)}))};function Jn(t,e,r){var n={},o=e.nspSet,a=t.useCallbackStyle;for(var i in o){var u=o[i];for(var c in u){var s=u[c];n=dn(n,c,Rn(i,c,s,qn(r,i,c,s,a),r,a))}}return n.devHelpers={getNsp:function(){return Object.keys(o)},getVer:function(){return t.version||"NOT SET"}},Promise.resolve(n)}function In(t,e,r){var n=e.nspSet,o=t.useCallbackStyle,a=t.enableAuth,i=[Jn];return o?i.push((function(t){return function(t,e,r,n){return dn(t,"on",(function(t,n){if(on(t)&&pn(n))switch(t){case"error":for(var o in r)e.$on(ln(o,"error"),n);break;case"login":e.$only("login",n);break;case"ready":e.$on("ready",n);break;default:e.$trigger("error",new l("on","Unknown event name "+t+"!"))}}))}(t,r,n)})):(i.push((function(t){return function(t,e,r){return gn(t,"onError",(function(t){if(pn(t))for(var n in r)e.$on(ln(n,"onError"),t)}))}(t,r,n)}),(function(t){return function(t,e,r){return gn(t,"onReady",(function(t){pn(t)&&e.$on("onReady",t)}))}(t,r)})),a&&i.push((function(e){return function(t,e,r){return r.enableAuth?gn(t,"onLogin",(function(t){pn(t)&&e.$only("onLogin",t)})):t}(e,r,t)}))),a&&i.push((function(e){return function(t,e,r){return r.enableAuth?hn(Ln,Wn)(t,e,r):t}(e,r,t)})),Reflect.apply(vn,null,i)(t,e,r)}var Un=["roundtip","handshake"],Dn={useCallbackStyle:un(!1,["boolean"]),loginHandlerName:un("login",["string"]),logoutHandlerName:un("logout",["string"]),loginMethod:un("handshake",["string"],(Mn={},Mn.enumv=Un,Mn)),useJwt:un(!0,["boolean","string"]),authStrKey:un(null,["string"]),hostname:un(!1,["string"]),namespace:un("jsonql",["string"]),wsOptions:un({},["object"]),contract:un({},["object"],(Fn={},Fn.checker=function(t){return!!function(t){return gt(t)&&(fn(t,"query")||fn(t,"mutation")||fn(t,"socket"))}(t)&&t},Fn)),enableAuth:un(!1,["boolean"]),token:un(!1,["string"])},Hn={eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:""};function Vn(t){return Promise.resolve(t).then((function(t){var e;return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new f(t)}}()),t.wssPath=(e=[t.hostname,t.namespace].join("/"),"ws"===t.serverType?e.replace("http://","ws://"):e),t}))}function Bn(t,e,r){return function(t,e,r){var n=Object.assign(Hn,r),o=Object.assign(Dn,e);return cn(t,o,n)}(t,e,r).then(Vn)}var Yn=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];Reflect.apply(console.info,console,["[jsonql-ws-client-core]"].concat(t))},Kn=function(t){var e=t.log,r=t.eventEmitter;return e("CHECKED_KEY",t.__checked__),r?(e("eventEmitter is:",r.name),r):(e("Create a new Event Emitter"),new Sn(t.log))},Gn=function(t){var e=t.log;return e&&"function"==typeof e||(t.log=Yn),t.log("--- wsClientCore config opts ---",t),t};function Qn(t,e,r){return void 0===e&&(e={}),void 0===r&&(r={}),function(n){return void 0===n&&(n={}),Bn(n,e,r).then((function(e){return function(t,e){return Promise.resolve(e).then(Gn).then((function(t){return{opts:t,nspMap:kn(t),ee:Kn(t)}})).then((function(e){var r=e.opts,n=e.nspMap,o=e.ee;return t(r,n,o)})).then((function(t){return In(t.opts,t.nspMap,t.ee)})).catch((function(t){console.error("jsonql-ws-core-client init error",t)}))}(t,e)}))}}var Xn=null;"undefined"!=typeof WebSocket?Xn=WebSocket:"undefined"!=typeof MozWebSocket?Xn=MozWebSocket:void 0!==v?Xn=v.WebSocket||v.MozWebSocket:"undefined"!=typeof window?Xn=window.WebSocket||window.MozWebSocket:"undefined"!=typeof self&&(Xn=self.WebSocket||self.MozWebSocket);var Zn=function(t){var e=t.toLowerCase();return e.indexOf("http")>-1?e.indexOf("https")>-1?e.replace("https","wss"):e.replace("http","ws"):e};function to(t,e){return void 0===e&&(e=!1),!1===e?function(e){return new t(Zn(e))}:function(e,r){var n=Zn(e),o=r&&"string"==typeof r?n+"?token="+r:n;try{return new t(o)}catch(t){return console.error("WebSocket Connection Error",t),!1}}}function eo(t,e){var r=e.hostname,n=e.wssPath,o=e.wsOptions;return(0,e.nspClient)(t?[r,t].join("/"):n,o)}var ro=function(t,e,r){var n=r.useCallbackStyle,o=r.log,a=n?"error":"onError",i=n?"result":"onResult";e.$only(ln(t,"emit"),(function(r,n){o("[notLoginHandler] hijack the ws call",t,r,n);var u={message:"NOT LOGIN"};e.$call(ln(t,r,a),[u]),e.$call(ln(t,r,i),[{error:u}])}))};function no(t,e,r,n,o,a){var i=function(t){return t.length>1&&t[0]}(o),u=!1,c=t.log;o.forEach((function(o){if(u=i===o,a[o]){c("[call bindWsHandler]",u,o);var s=[o,a[o],r,u,t];if("socket.io"===t.serverType){var f=e.nspSet;s.push(f[o])}Reflect.apply(n,null,s)}else ro(o,r,t)})),r.$on("__logout__",(function(){c("LOGOUT_EVENT_NAME"),function(t,e,r,n){void 0===n&&(n={});var o=n.useCallbackStyle?"error":"onError";e.forEach((function(e){t.$call(ln(e,o),[{message:r,namespace:e}])}))}(r,o,"__logout__"),o.forEach((function(e){En(r,e),a[e]=!1,ro(e,r,t)}))}))}var oo=["__reply__","__event__","__data__"],ao=function(t){var e,r=t.data;if(!1!==(e=function(t){var e=t.data;return!!e&&(oo.filter((function(t){return fn(e,t)})).length===oo.length&&e)}(on(r)?JSON.parse(r):r)))return{resolverName:e.__event__,data:e.__data__,type:e.__reply__};throw new l("payload can not be decoded",t)},io=function(t,e,r,n,o){var a=[e];r&&a.push(r),a.push(o);var i=Reflect.apply(ln,null,a),u=n.data||n;t.$trigger(i,[u])};function uo(t,e,r,n,o){var a=o.useCallbackStyle,i=o.log;i("wsMainHandler log test");var u=a?"ready":"onReady",c=a?"login":"onLogin",s=a?"message":"onMessage",f=a?"result":"onResult",l=a?"error":"onError";e.onopen=function(){i("ws.onopen listened"),r.$call(u,t),n&&(i("isPrivate and fire the "+c),r.$call(c,t)),r.$only(ln(t,"emit"),(function(t,r){i("calling server",t,r),e.send(function(t,e,r){return void 0===e&&(e=[]),void 0===r&&(r=!1),JSON.stringify(_n(t,e,r))}(t,r))}))},e.onmessage=function(e){try{var n=ao(e),o=n.resolverName,a=n.type;switch(i("Hear from server",a,n),a){case"emit":var u=ln(t,o,s),c=r.$trigger(u,[n]);i("EMIT_REPLY_TYPE",u,c);break;case"acknowledge":var p=ln(t,o,f);r.$trigger(p,[n]);break;case"error":i("ERROR_TYPE"),io(r,t,o,n,l);break;default:i("Unhandled event!",n),io(r,t,o,n,l)}}catch(e){console.error("ws.onmessage error",e),io(r,t,!1,e,l)}},e.onclose=function(){i("ws.onclose callback")},r.$on("__logout__",(function(){try{i("terminate ws connection"),e.terminate()}catch(t){console.error("ws.terminate error",t)}}))}var co=function(t,e,r){var n,o=e.nspSet,a=e.publicNamespace,i=!1,u=[],c={};if(t.enableAuth)i=!0,c=(u=function(t,e){var r=[];for(var n in t)n===e?r[1]=n:r[0]=n;return r}(o,a)).map((function(e,n){var o,a,i;return 0===n?r?(t.token=r,(o={})[e]=function(t,e){var r=e.hostname,n=e.wssPath,o=e.token,a=e.wsOptions,i=e.nspAuthClient,u=t?[r,t].join("/"):n;if(o&&"string"!=typeof o)throw new Error("Expect token to be string, but got "+o);return i(u,o,a)}(e,t),o):((a={})[e]=!1,a):((i={})[e]=eo(e,t),i)})).reduce((function(t,e){return Object.assign(t,e)}),{});else{var s=(n=o,Object.keys(n)[0]);u.push(s),c[s]=eo(!1,t)}return{nsps:c,namespaces:u,login:i}};var so=function(t){var e=to(t),r=to(t,!0);return function(t,n,o){t.nspClient=e,t.nspAuthClient=r;var a=t.log;return a&&"function"==typeof a&&(a("@jsonql/ws ee",o.name),a("@jsonql/ws createClientResolver",t)),function(t,e,r){var n=[t,e,r,uo],o=t.token,a=t.log,i=co(t,e,o),u=i.nsps,c=i.namespaces,s=i.login;return Reflect.apply(no,null,n.concat([c,u])),s&&r.$only("__login__",(function(o){a("createClient LOGIN_EVENT_NAME"),En(r,c);var i=co(t,e,o);Reflect.apply(no,null,n.concat([i.namespaces,i.nsps]))})),{opts:t,nspMap:e,ee:r}}(t,n,o)}}(Xn),fo={version:"version: 1.1.0 module: umd",serverType:"ws"},lo={};return function(t,e){return void 0===t&&(t={}),void 0===e&&(e={}),Qn(so,lo,Object.assign(fo,e))(t)}})); //# sourceMappingURL=jsonql-ws-client.umd.js.map diff --git a/packages/@jsonql/ws/main.js b/packages/@jsonql/ws/main.js new file mode 100644 index 00000000..c3cf670b --- /dev/null +++ b/packages/@jsonql/ws/main.js @@ -0,0 +1,2 @@ +"use strict";var t,r=(t=require("ws"))&&"object"==typeof t&&"default"in t?t.default:t,e=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 406},e.name.get=function(){return"Jsonql406Error"},Object.defineProperties(r,e),r}(Error),n=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 500},e.name.get=function(){return"Jsonql500Error"},Object.defineProperties(r,e),r}(Error),o=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 403},e.name.get=function(){return"JsonqlForbiddenError"},Object.defineProperties(r,e),r}(Error),a=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 401},e.name.get=function(){return"JsonqlAuthorisationError"},Object.defineProperties(r,e),r}(Error),i=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 401},e.name.get=function(){return"JsonqlContractAuthError"},Object.defineProperties(r,e),r}(Error),u=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 500},e.name.get=function(){return"JsonqlResolverAppError"},Object.defineProperties(r,e),r}(Error),c=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 404},e.name.get=function(){return"JsonqlResolverNotFoundError"},Object.defineProperties(r,e),r}(Error),s=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlEnumError"},Object.defineProperties(r,e),r}(Error),f=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlTypeError"},Object.defineProperties(r,e),r}(Error),l=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlCheckerError"},Object.defineProperties(r,e),r}(Error),p=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(r,e),r}(Error),h=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0},statusCode:{configurable:!0}};return e.name.get=function(){return"JsonqlError"},e.statusCode.get=function(){return-1},Object.defineProperties(r,e),r}(Error),v=function(t){function r(e,n){t.call(this,n),this.statusCode=e,this.className=r.name}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlServerError"},Object.defineProperties(r,e),r}(Error);function g(t){if(Array.isArray(t))throw new p("",t);var r=t.message||"No message",g=t.detail||t;switch(!0){case t instanceof e:throw new e(r,g);case t instanceof n:throw new n(r,g);case t instanceof o:throw new o(r,g);case t instanceof a:throw new a(r,g);case t instanceof i:throw new i(r,g);case t instanceof u:throw new u(r,g);case t instanceof c:throw new c(r,g);case t instanceof s:throw new s(r,g);case t instanceof f:throw new f(r,g);case t instanceof l:throw new l(r,g);case t instanceof p:throw new p(r,g);case t instanceof v:throw new v(r,g);default:throw new h(r,g)}}var y="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},d="object"==typeof y&&y&&y.Object===Object&&y,b="object"==typeof self&&self&&self.Object===Object&&self,_=d||b||Function("return this")(),m=_.Symbol;function w(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 a=Array(o);++n-1;);return e}(n,o),function(t,r){for(var e=t.length;e--&&M(r,t[e],0)>-1;);return e}(n,o)+1).join("")}var Z=function(t){return!!j(t)||null!=t&&""!==X(t)};function tt(t){return function(t){return"number"==typeof t||P(t)&&"[object Number]"==A(t)}(t)&&t!=+t}function rt(t){return"string"==typeof t||!j(t)&&P(t)&&"[object String]"==A(t)}var et=function(t){return!rt(t)&&!tt(parseFloat(t))},nt=function(t){return""!==X(t)&&rt(t)},ot=function(t){return null!=t&&"boolean"==typeof t},at=function(t,r){return void 0===r&&(r=!0),void 0!==t&&""!==t&&""!==X(t)&&(!1===r||!0===r&&null!==t)},it=function(t){switch(t){case"number":return et;case"string":return nt;case"boolean":return ot;default:return at}},ut=function(t,r){return void 0===r&&(r=""),!!j(t)&&(""===r||""===X(r)||!(t.filter((function(t){return!it(r)(t)})).length>0))},ct=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var r=t.replace("array.<","").replace(">","");return r.indexOf("|")?r.split("|"):[r]}return!1},st=function(t,r){var e=t.arg;return r.length>1?!e.filter((function(t){return!(r.length>r.filter((function(r){return!it(r)(t)})).length)})).length:r.length>r.filter((function(t){return!ut(e,t)})).length};function ft(t,r){return function(e){return t(r(e))}}var lt=ft(Object.getPrototypeOf,Object),pt=Function.prototype,ht=Object.prototype,vt=pt.toString,gt=ht.hasOwnProperty,yt=vt.call(Object);function dt(t){if(!P(t)||"[object Object]"!=A(t))return!1;var r=lt(t);if(null===r)return!0;var e=gt.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&vt.call(e)==yt}var bt,_t=function(t,r,e){for(var n=-1,o=Object(t),a=e(t),i=a.length;i--;){var u=a[bt?i:++n];if(!1===r(o[u],u,o))break}return t};function mt(t){return P(t)&&"[object Arguments]"==A(t)}var wt=Object.prototype,jt=wt.hasOwnProperty,Ot=wt.propertyIsEnumerable,St=mt(function(){return arguments}())?mt:function(t){return P(t)&&jt.call(t,"callee")&&!Ot.call(t,"callee")};var kt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Et=kt&&"object"==typeof module&&module&&!module.nodeType&&module,$t=Et&&Et.exports===kt?_.Buffer:void 0,Tt=($t?$t.isBuffer:void 0)||function(){return!1},At=/^(?:0|[1-9]\d*)$/;function Pt(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&At.test(t))&&t>-1&&t%1==0&&t-1&&t%1==0&&t<=9007199254740991}var zt={};zt["[object Float32Array]"]=zt["[object Float64Array]"]=zt["[object Int8Array]"]=zt["[object Int16Array]"]=zt["[object Int32Array]"]=zt["[object Uint8Array]"]=zt["[object Uint8ClampedArray]"]=zt["[object Uint16Array]"]=zt["[object Uint32Array]"]=!0,zt["[object Arguments]"]=zt["[object Array]"]=zt["[object ArrayBuffer]"]=zt["[object Boolean]"]=zt["[object DataView]"]=zt["[object Date]"]=zt["[object Error]"]=zt["[object Function]"]=zt["[object Map]"]=zt["[object Number]"]=zt["[object Object]"]=zt["[object RegExp]"]=zt["[object Set]"]=zt["[object String]"]=zt["[object WeakMap]"]=!1;var Ct,xt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Rt=xt&&"object"==typeof module&&module&&!module.nodeType&&module,qt=Rt&&Rt.exports===xt&&d.process,Mt=function(){try{var t=Rt&&Rt.require&&Rt.require("util").types;return t||qt&&qt.binding&&qt.binding("util")}catch(t){}}(),Ft=Mt&&Mt.isTypedArray,Lt=Ft?(Ct=Ft,function(t){return Ct(t)}):function(t){return P(t)&&Nt(t.length)&&!!zt[A(t)]},Jt=Object.prototype.hasOwnProperty;function It(t,r){var e=j(t),n=!e&&St(t),o=!e&&!n&&Tt(t),a=!e&&!n&&!o&&Lt(t),i=e||n||o||a,u=i?function(t,r){for(var e=-1,n=Array(t);++e-1},tr.prototype.set=function(t,r){var e=this.__data__,n=Xt(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};var rr,er=_["__core-js_shared__"],nr=(rr=/[^.]+$/.exec(er&&er.keys&&er.keys.IE_PROTO||""))?"Symbol(src)_1."+rr:"";var or=Function.prototype.toString;function ar(t){if(null!=t){try{return or.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var ir=/^\[object .+?Constructor\]$/,ur=Function.prototype,cr=Object.prototype,sr=ur.toString,fr=cr.hasOwnProperty,lr=RegExp("^"+sr.call(fr).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pr(t){return!(!Bt(t)||function(t){return!!nr&&nr in t}(t))&&(Wt(t)?lr:ir).test(ar(t))}function hr(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pr(e)?e:void 0}var vr=hr(_,"Map"),gr=hr(Object,"create");var yr=Object.prototype.hasOwnProperty;var dr=Object.prototype.hasOwnProperty;function br(t){var r=-1,e=null==t?0:t.length;for(this.clear();++ru))return!1;var s=a.get(t);if(s&&a.get(r))return s==r;var f=-1,l=!0,p=2&e?new jr:void 0;for(a.set(t,r),a.set(r,t);++fr.type.filter((function(t){var r;return void 0===e||(!1!==(r=ct(t))?!st({arg:e},r):!it(t)(e))})).length)})).length}return!1},be=function(t,r){var e,n,o,a,i;switch(!0){case"object"===t:return o=(n=r).arg,a=n.param,i=[o],Array.isArray(a.keys)&&a.keys.length&&i.push(a.keys),!Reflect.apply(de,null,i);case"array"===t:return!ut(r.arg);case!1!==(e=ct(t)):return!st(r,e);default:return!it(t)(r.arg)}},_e=function(t,r){return void 0!==t?t:!0===r.optional&&void 0!==r.defaultvalue?r.defaultvalue:null},me=function(t,r,e){var n;void 0===e&&(e=!1);var o=function(t,r){if(!ut(r))throw new h("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===r.length)return[];if(!ut(t))throw new h("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==r.length:return t.map((function(t,e){return{arg:t,index:e,param:r[e]}}));case!0===r[0].variable:var e=r[0].type;return t.map((function(t,n){return{arg:t,index:n,param:r[n]||{type:e,name:"_"}}}));case t.lengthr.length:var n=r.length,o=["any"];return t.map((function(t,e){var a=e>=n||!!r[e].optional,i=r[e]||{type:o,name:"_"+e};return{arg:a?_e(t,i):t,index:e,param:i,optional:a}}));default:throw new h("Could not understand your arguments and parameter structure!",{args:t,params:r})}}(t,r),a=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var r=t.arg,e=t.param;return!!Z(r)&&!(e.type.length>e.type.filter((function(r){return be(r,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(r){return be(r,t)})).length)}));return e?((n={}).error=a,n.data=o.map((function(t){return t.arg})),n):a},we=function(){try{var t=hr(Object,"defineProperty");return t({},"",{}),t}catch(t){}}();function je(t,r,e){"__proto__"==r&&we?we(t,r,{configurable:!0,enumerable:!0,value:e,writable:!0}):t[r]=e}function Oe(t,r,e){(void 0===e||Qt(t[r],e))&&(void 0!==e||r in t)||je(t,r,e)}var Se="object"==typeof exports&&exports&&!exports.nodeType&&exports,ke=Se&&"object"==typeof module&&module&&!module.nodeType&&module,Ee=ke&&ke.exports===Se?_.Buffer:void 0,$e=Ee?Ee.allocUnsafe:void 0;function Te(t,r){var e,n,o=r?(e=t.buffer,n=new e.constructor(e.byteLength),new kr(n).set(new kr(e)),n):t.buffer;return new t.constructor(o,t.byteOffset,t.length)}var Ae=Object.create,Pe=function(){function t(){}return function(r){if(!Bt(r))return{};if(Ae)return Ae(r);t.prototype=r;var e=new t;return t.prototype=void 0,e}}();function Ne(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var ze=Object.prototype.hasOwnProperty;function Ce(t,r,e){var n=t[r];ze.call(t,r)&&Qt(n,e)&&(void 0!==e||r in t)||je(t,r,e)}var xe=Object.prototype.hasOwnProperty;function Re(t){if(!Bt(t))return function(t){var r=[];if(null!=t)for(var e in Object(t))r.push(e);return r}(t);var r=Dt(t),e=[];for(var n in t)("constructor"!=n||!r&&xe.call(t,n))&&e.push(n);return e}function qe(t){return Yt(t)?It(t,!0):Re(t)}function Me(t){return function(t,r,e,n){var o=!e;e||(e={});for(var a=-1,i=r.length;++a0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(Ue);function Ve(t,r){return He(function(t,r,e){return r=Ie(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,a=Ie(n.length-r,0),i=Array(a);++o1?r[n-1]:void 0,a=n>2?r[2]:void 0;for(o=Be.length>3&&"function"==typeof o?(n--,o):void 0,a&&function(t,r,e){if(!Bt(e))return!1;var n=typeof r;return!!("number"==n?Yt(e)&&Pt(r,e.length):"string"==n&&r in e)&&Qt(e[r],t)}(r[0],r[1],a)&&(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,ln(t))}),Reflect.apply(t,null,e))}};function yn(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))}}function dn(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}function bn(t,r,e,n){void 0===n&&(n=!1);var o=function(t,r){var e=Object.getOwnPropertyDescriptor(t,r);return void 0!==e&&e.value?e.value:e}(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t}function _n(t){return!!pn(t,"socket")&&t.socket}var mn=function(t){void 0===t&&(t=!1);var r=Date.now();return t?Math.floor(r/1e3):r};function wn(t,r,e){if(void 0===r&&(r=[]),void 0===e&&(e=!1),rt(t)&&j(r)){var n=function(t){var r;return(r={}).args=t,r}(r);return!0===e?n:function(t,r){var e;return(e={})[t]=r,e.TS=[mn()],e}(t,n)}throw new p("[createQuery] expect resolverName to be string and args to be array!",{resolverName:t,args:r})}var jn=new WeakMap,On=new WeakMap;var Sn=function(){this.__suspend__=null,this.queueStore=new Set},kn={$suspend:{configurable:!0},$queues:{configurable:!0}};kn.$suspend.set=function(t){var r=this;if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value!");var e=this.__suspend__;this.__suspend__=t,this.logger("($suspend)","Change from "+e+" --\x3e "+t),!0===e&&!1===t&&setTimeout((function(){r.release()}),1)},Sn.prototype.$queue=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return!0===this.__suspend__&&(this.logger("($queue)","added to $queue",t),this.queueStore.add(t)),this.__suspend__},kn.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},Sn.prototype.release=function(){var t=this,r=this.queueStore.size;if(this.logger("(release)","Release was called "+r),r>0){var e=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",e),e.forEach((function(r){t.logger(r),Reflect.apply(t.$trigger,t,r)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(Sn.prototype,kn);var En=function(t){function r(r){if("function"!=typeof r)throw new Error("Just die here the logger is not a function!");t.call(this,{logger:r})}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(r.prototype,e),r}(function(t){function r(r){void 0===r&&(r={}),t.call(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={$done:{configurable:!0}};return r.prototype.logger=function(){},r.prototype.$on=function(t,r,e){var n=this;void 0===e&&(e=null);this.validate(t,r);var o=this.takeFromStore(t);if(!1===o)return this.logger("($on)",t+" callback is not in lazy store"),this.addToNormalStore(t,"on",r,e);this.logger("($on)",t+" found in lazy store");var a=0;return o.forEach((function(o){var i=o[0],u=o[1],c=o[2];if(c&&"on"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);n.logger("($on)","call run on "+t),n.run(r,i,e||u),a+=n.addToNormalStore(t,"on",r,e||u)})),a},r.prototype.$once=function(t,r,e){void 0===e&&(e=null),this.validate(t,r);var n=this.takeFromStore(t);this.normalStore;if(!1===n)return this.logger("($once)",t+" not in the lazy store"),this.addToNormalStore(t,"once",r,e);this.logger("($once)",n);var o=Array.from(n)[0],a=o[0],i=o[1],u=o[2];if(u&&"once"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);this.logger("($once)","call run for "+t),this.run(r,a,e||i),this.$off(t)},r.prototype.$only=function(t,r,e){var n=this;void 0===e&&(e=null),this.validate(t,r);var o=!1,a=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger("($only)",t+" add to store"),o=this.addToNormalStore(t,"only",r,e)),!1!==a)&&(this.logger("($only)",t+" found data in lazy store to execute"),Array.from(a).forEach((function(o){var a=o[0],i=o[1],u=o[2];if(u&&"only"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);n.logger("($only)","call run for "+t),n.run(r,a,e||i)})));return o},r.prototype.$onlyOnce=function(t,r,e){void 0===e&&(e=null),this.validate(t,r);var n=!1,o=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger("($onlyOnce)",t+" add to store"),n=this.addToNormalStore(t,"onlyOnce",r,e)),!1!==o){this.logger("($onlyOnce)",o);var a=Array.from(o)[0],i=a[0],u=a[1],c=a[2];if(c&&"onlyOnce"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);this.logger("($onlyOnce)","call run for "+t),this.run(r,i,e||u),this.$off(t)}return n},r.prototype.$replace=function(t,r,e,n){if(void 0===e&&(e=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,r),Reflect.apply(o,this,[t,r,e])}throw new Error(n+" is not supported!")},r.prototype.$trigger=function(t,r,e,n){void 0===r&&(r=[]),void 0===e&&(e=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,a=this.normalStore;if(this.logger("($trigger)","normalStore",a),a.has(t)){var i=this.$queue(t,r,e,n);if(this.logger("($trigger)",t,"found; add to queue: ",i),!0===i)return this.logger("($trigger)",t,"not executed. Exit now."),!1;for(var u=Array.from(a.get(t)),c=u.length,s=!1,f=0;f0;)n[o]=arguments[o+2];if(t.has(r)?(this.logger("(addToStore)",r+" existed"),e=t.get(r)):(this.logger("(addToStore)","create new Set for "+r),e=new Set),n.length>2)if(Array.isArray(n[0])){var a=n[2];this.checkTypeInLazyStore(r,a)||e.add(n)}else this.checkContentExist(n,e)||(this.logger("(addToStore)","insert new",n),e.add(n));else e.add(n);return t.set(r,e),[t,e.size]},r.prototype.checkContentExist=function(t,r){return!!Array.from(r).filter((function(r){return r[0]===t[0]})).length},r.prototype.checkTypeInStore=function(t,r){this.validateEvt(t,r);var e=this.$get(t,!0);return!1===e||!e.filter((function(t){var e=t[3];return r!==e})).length},r.prototype.checkTypeInLazyStore=function(t,r){this.validateEvt(t,r);var e=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",e),!!e&&!!Array.from(e).filter((function(t){return t[2]!==r})).length},r.prototype.addToNormalStore=function(t,r,e,n){if(void 0===n&&(n=null),this.logger("(addToNormalStore)",t,r,"try to add to normal store"),this.checkTypeInStore(t,r)){this.logger("(addToNormalStore)",r+" can add to "+t+" normal store");var o=this.hashFnToKey(e),a=[this.normalStore,t,o,e,n,r],i=Reflect.apply(this.addToStore,this,a),u=i[0],c=i[1];return this.normalStore=u,c}return!1},r.prototype.addToLazyStore=function(t,r,e,n){void 0===r&&(r=[]),void 0===e&&(e=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(r),e];n&&o.push(n);var a=Reflect.apply(this.addToStore,this,o),i=a[0],u=a[1];return this.lazyStore=i,u},r.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},e.normalStore.set=function(t){jn.set(this,t)},e.normalStore.get=function(){return jn.get(this)},e.lazyStore.set=function(t){On.set(this,t)},e.lazyStore.get=function(){return On.get(this)},r.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,r){return(t=(t<<5)-t+r.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(r.prototype,e),r}(Sn)));function $n(t){var r,e,n=t.contract;return t.enableAuth?function(t,r){void 0===r&&(r=!1);var e=_n(t);if(!1===e){if(r)return t;throw new h("socket not found in contract!")}var n,o={},a=0;for(var i in e){var u=e[i],c=u.namespace;c&&(o[c]||(++a,o[c]={}),o[c][i]=u,n||u.public&&(n=c))}return{size:a,nspSet:o,publicNamespace:n}}(n):((e={}).nspSet=((r={}).jsonql=function(t){var r=_n(t);if(!1!==r)return r;throw new c("Missing property in contract!")}(n),r),e.publicNamespace="jsonql",e)}var Tn=function(t,r){ln(r).forEach((function(r){t.$off(hn(r,"emit"))}))};function An(t,r,e){pn(t,"error")?e(t.error):pn(t,"data")?r(t.data):e({message:"UKNNOWN RESULT!",error:t})}function Pn(t,r,e,n,o){void 0===o&&(o=[]);var a=hn(r,"emit"),i=n?"result":"onResult";return t.$trigger(a,[e,ln(o)]),new Promise((function(n,o){t.$on(hn(r,e,i),(function(t){An(t,n,o)}))}))}var Nn=function(t,r,e,n,o,a){return dn(t,"send",(function(t){var i=a?"error":"onError";cn(ln(t),o.params,!0).then((function(o){if(!o.error||!o.error.length)return Pn(r,e,n,a,t);r.$call(hn(e,n,i),[new p(n,o.error)])})).catch((function(t){r.$call(hn(e,n,i),[new p(n,t)])}))}),(function(){return function(){for(var t=[],i=arguments.length;i--;)t[i]=arguments[i];return cn(t,o.params,!0).then((function(t){return Pn(r,e,n,a,t)})).catch(g)}}))};function zn(t,r,e,n,o){return[bn(t,"on",(function(t,o){if(un(t)&&vn(o))switch(t){case"result":r.$on(hn(e,n,"onResult"),(function(t){An(t,o,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}));break;case"message":r.$only(hn(e,n,"onMessage"),(function(t){An(t,o,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}));break;case"ready":r.$only(hn(e,n,"onError"),o);break;default:r.$trigger(hn(e,n,"onError"),new h(n,"Unknown event name "+t+"!"))}})),r,e,n,o]}var Cn=function(t,r,e,n,o,a){return[bn(t,"myNamespace",e),r,e,n,o,a]},xn=function(t,r,e,n,o,a){return[dn(t,"onResult",(function(t){vn(t)&&r.$on(hn(e,n,"onResult"),(function(o){An(o,t,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}))})),r,e,n,o,a]},Rn=function(t,r,e,n,o,a){return[dn(t,"onMessage",(function(t){if(vn(t)){r.$only(hn(e,n,"onMessage"),(function(o){An(o,t,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}))}})),r,e,n,o,a]},qn=function(t,r,e,n,o,a){return[dn(t,"onError",(function(t){vn(t)&&r.$only(hn(e,n,"onError"),t)})),r,e,n,o,a]};function Mn(t,r,e,n,o,a){var i=[Cn];a?i.push(zn):i.push(xn,Rn,qn),i.push(Nn);var u=Reflect.apply(gn,null,i);return Reflect.apply(u,null,[n,o,t,r,e,a])}function Fn(t,r,e,n,o){return function(){for(var a=[],i=arguments.length;i--;)a[i]=arguments[i];return cn(a,n.params,!0).then((function(n){return Pn(t,r,e,o,n)})).catch(g)}}var Ln,Jn,In=function(t,r,e){return[bn(t,e.loginHandlerName,(function(t){if(t&&un(t))return r.$trigger("__login__",[t]);throw new p(e.loginHandlerName,"Unexpected token "+t)})),r,e]},Un=function(t,r,e){return bn(t,e.logoutHandlerName,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__logout__",t)}))};function Dn(t,r,e){var n={},o=r.nspSet,a=t.useCallbackStyle;for(var i in o){var u=o[i];for(var c in u){var s=u[c];n=bn(n,c,Mn(i,c,s,Fn(e,i,c,s,a),e,a))}}return n.devHelpers={getNsp:function(){return Object.keys(o)},getVer:function(){return t.version||"NOT SET"}},Promise.resolve(n)}function Hn(t,r,e){var n=r.nspSet,o=t.useCallbackStyle,a=t.enableAuth,i=[Dn];return o?i.push((function(t){return function(t,r,e,n){return bn(t,"on",(function(t,n){if(un(t)&&vn(n))switch(t){case"error":for(var o in e)r.$on(hn(o,"error"),n);break;case"login":r.$only("login",n);break;case"ready":r.$on("ready",n);break;default:r.$trigger("error",new h("on","Unknown event name "+t+"!"))}}))}(t,e,n)})):(i.push((function(t){return function(t,r,e){return dn(t,"onError",(function(t){if(vn(t))for(var n in e)r.$on(hn(n,"onError"),t)}))}(t,e,n)}),(function(t){return function(t,r,e){return dn(t,"onReady",(function(t){vn(t)&&r.$on("onReady",t)}))}(t,e)})),a&&i.push((function(r){return function(t,r,e){return e.enableAuth?dn(t,"onLogin",(function(t){vn(t)&&r.$only("onLogin",t)})):t}(r,e,t)}))),a&&i.push((function(r){return function(t,r,e){return e.enableAuth?gn(In,Un)(t,r,e):t}(r,e,t)})),Reflect.apply(yn,null,i)(t,r,e)}var Vn=["roundtip","handshake"],Bn={useCallbackStyle:sn(!1,["boolean"]),loginHandlerName:sn("login",["string"]),logoutHandlerName:sn("logout",["string"]),loginMethod:sn("handshake",["string"],(Ln={},Ln.enumv=Vn,Ln)),useJwt:sn(!0,["boolean","string"]),authStrKey:sn(null,["string"]),hostname:sn(!1,["string"]),namespace:sn("jsonql",["string"]),wsOptions:sn({},["object"]),contract:sn({},["object"],(Jn={},Jn.checker=function(t){return!!function(t){return dt(t)&&(pn(t,"query")||pn(t,"mutation")||pn(t,"socket"))}(t)&&t},Jn)),enableAuth:sn(!1,["boolean"]),token:sn(!1,["string"])},Wn={eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:""};function Yn(t){return Promise.resolve(t).then((function(t){var r;return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new p(t)}}()),t.wssPath=(r=[t.hostname,t.namespace].join("/"),"ws"===t.serverType?r.replace("http://","ws://"):r),t}))}function Kn(t,r,e){return function(t,r,e){var n=Object.assign(Wn,e),o=Object.assign(Bn,r);return fn(t,o,n)}(t,r,e).then(Yn)}var Gn=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];Reflect.apply(console.info,console,["[jsonql-ws-client-core]"].concat(t))},Qn=function(t){var r=t.log,e=t.eventEmitter;return r("CHECKED_KEY",t.__checked__),e?(r("eventEmitter is:",e.name),e):(r("Create a new Event Emitter"),new En(t.log))},Xn=function(t){var r=t.log;return r&&"function"==typeof r||(t.log=Gn),t.log("--- wsClientCore config opts ---",t),t};function Zn(t,r,e){return void 0===r&&(r={}),void 0===e&&(e={}),function(n){return void 0===n&&(n={}),Kn(n,r,e).then((function(r){return function(t,r){return Promise.resolve(r).then(Xn).then((function(t){return{opts:t,nspMap:$n(t),ee:Qn(t)}})).then((function(r){var e=r.opts,n=r.nspMap,o=r.ee;return t(e,n,o)})).then((function(t){return Hn(t.opts,t.nspMap,t.ee)})).catch((function(t){console.error("jsonql-ws-core-client init error",t)}))}(t,r)}))}}var to={version:"version: 1.1.0 module: cjs",serverType:"ws"},ro={},eo=function(t){var r=t.toLowerCase();return r.indexOf("http")>-1?r.indexOf("https")>-1?r.replace("https","wss"):r.replace("http","ws"):r};function no(t,r){return void 0===r&&(r=!1),!1===r?function(r){return new t(eo(r))}:function(r,e){var n=eo(r),o=e&&"string"==typeof e?n+"?token="+e:n;try{return new t(o)}catch(t){return console.error("WebSocket Connection Error",t),!1}}}function oo(t,r){var e=r.hostname,n=r.wssPath,o=r.wsOptions;return(0,r.nspClient)(t?[e,t].join("/"):n,o)}var ao=function(t,r,e){var n=e.useCallbackStyle,o=e.log,a=n?"error":"onError",i=n?"result":"onResult";r.$only(hn(t,"emit"),(function(e,n){o("[notLoginHandler] hijack the ws call",t,e,n);var u={message:"NOT LOGIN"};r.$call(hn(t,e,a),[u]),r.$call(hn(t,e,i),[{error:u}])}))};function io(t,r,e,n,o,a){var i=function(t){return t.length>1&&t[0]}(o),u=!1,c=t.log;o.forEach((function(o){if(u=i===o,a[o]){c("[call bindWsHandler]",u,o);var s=[o,a[o],e,u,t];if("socket.io"===t.serverType){var f=r.nspSet;s.push(f[o])}Reflect.apply(n,null,s)}else ao(o,e,t)})),e.$on("__logout__",(function(){c("LOGOUT_EVENT_NAME"),function(t,r,e,n){void 0===n&&(n={});var o=n.useCallbackStyle?"error":"onError";r.forEach((function(r){t.$call(hn(r,o),[{message:e,namespace:r}])}))}(e,o,"__logout__"),o.forEach((function(r){Tn(e,r),a[r]=!1,ao(r,e,t)}))}))}var uo=["__reply__","__event__","__data__"],co=function(t){var r,e=t.data;if(!1!==(r=function(t){var r=t.data;return!!r&&(uo.filter((function(t){return pn(r,t)})).length===uo.length&&r)}(un(e)?JSON.parse(e):e)))return{resolverName:r.__event__,data:r.__data__,type:r.__reply__};throw new h("payload can not be decoded",t)},so=function(t,r,e,n,o){var a=[r];e&&a.push(e),a.push(o);var i=Reflect.apply(hn,null,a),u=n.data||n;t.$trigger(i,[u])};function fo(t,r,e,n,o){var a=o.useCallbackStyle,i=o.log;i("wsMainHandler log test");var u=a?"ready":"onReady",c=a?"login":"onLogin",s=a?"message":"onMessage",f=a?"result":"onResult",l=a?"error":"onError";r.onopen=function(){i("ws.onopen listened"),e.$call(u,t),n&&(i("isPrivate and fire the "+c),e.$call(c,t)),e.$only(hn(t,"emit"),(function(t,e){i("calling server",t,e),r.send(function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(wn(t,r,e))}(t,e))}))},r.onmessage=function(r){try{var n=co(r),o=n.resolverName,a=n.type;switch(i("Hear from server",a,n),a){case"emit":var u=hn(t,o,s),c=e.$trigger(u,[n]);i("EMIT_REPLY_TYPE",u,c);break;case"acknowledge":var p=hn(t,o,f);e.$trigger(p,[n]);break;case"error":i("ERROR_TYPE"),so(e,t,o,n,l);break;default:i("Unhandled event!",n),so(e,t,o,n,l)}}catch(r){console.error("ws.onmessage error",r),so(e,t,!1,r,l)}},r.onclose=function(){i("ws.onclose callback")},e.$on("__logout__",(function(){try{i("terminate ws connection"),r.terminate()}catch(t){console.error("ws.terminate error",t)}}))}var lo=function(t,r,e){var n,o=r.nspSet,a=r.publicNamespace,i=!1,u=[],c={};if(t.enableAuth)i=!0,c=(u=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e}(o,a)).map((function(r,n){var o,a,i;return 0===n?e?(t.token=e,(o={})[r]=function(t,r){var e=r.hostname,n=r.wssPath,o=r.token,a=r.wsOptions,i=r.nspAuthClient,u=t?[e,t].join("/"):n;if(o&&"string"!=typeof o)throw new Error("Expect token to be string, but got "+o);return i(u,o,a)}(r,t),o):((a={})[r]=!1,a):((i={})[r]=oo(r,t),i)})).reduce((function(t,r){return Object.assign(t,r)}),{});else{var s=(n=o,Object.keys(n)[0]);u.push(s),c[s]=oo(!1,t)}return{nsps:c,namespaces:u,login:i}};var po,ho,vo,go=(ho=no(po=r),vo=no(po,!0),function(t,r,e){t.nspClient=ho,t.nspAuthClient=vo;var n=t.log;return n&&"function"==typeof n&&(n("@jsonql/ws ee",e.name),n("@jsonql/ws createClientResolver",t)),function(t,r,e){var n=[t,r,e,fo],o=t.token,a=t.log,i=lo(t,r,o),u=i.nsps,c=i.namespaces,s=i.login;return Reflect.apply(io,null,n.concat([c,u])),s&&e.$only("__login__",(function(o){a("createClient LOGIN_EVENT_NAME"),Tn(e,c);var i=lo(t,r,o);Reflect.apply(io,null,n.concat([i.namespaces,i.nsps]))})),{opts:t,nspMap:r,ee:e}}(t,r,e)});module.exports=function(t,r){return void 0===t&&(t={}),void 0===r&&(r={}),Zn(go,ro,Object.assign(to,r))(t)}; +//# sourceMappingURL=main.js.map diff --git a/packages/@jsonql/ws/main.js.map b/packages/@jsonql/ws/main.js.map new file mode 100644 index 00000000..aee0a927 --- /dev/null +++ b/packages/@jsonql/ws/main.js.map @@ -0,0 +1 @@ +{"version":3,"file":"main.js","sources":[],"sourcesContent":[],"names":[],"mappings":""} \ No newline at end of file diff --git a/packages/@jsonql/ws/package.json b/packages/@jsonql/ws/package.json index 65174879..7b17a58b 100644 --- a/packages/@jsonql/ws/package.json +++ b/packages/@jsonql/ws/package.json @@ -2,13 +2,15 @@ "name": "@jsonql/ws", "version": "1.1.0", "description": "jsonql WS (WebSocket) client module for browser / node", - "main": "node.js", + "main": "main.js", "browser": "dist/jsonql-ws.umd.js", "module": "index.js", "files": [ "dist", "src", "index.js", + "main.js", + "main.js.map", "node.js", "node.js.map" ], diff --git a/packages/@jsonql/ws/rollup.config.js b/packages/@jsonql/ws/rollup.config.js index 71398802..125031e3 100644 --- a/packages/@jsonql/ws/rollup.config.js +++ b/packages/@jsonql/ws/rollup.config.js @@ -51,9 +51,14 @@ if (process.env.NODE_ENV === 'production') { } plugins.push( size() ) - +// @TODO there will be more and need to change how this take the file const inFile = target === 'cjs' ? 'src/node.js' : 'index.js' -const outFile = target === 'cjs' ? join(__dirname, 'node.js') : join(__dirname, 'dist', `jsonql-ws-client.${target}.js`) +const outFile = target === 'cjs' + ? join(__dirname, 'main.js') + : join(__dirname, 'dist', `jsonql-ws-client.${target}.js`) + + + let config = { input: join(__dirname, inFile), diff --git a/packages/@jsonql/ws/src/node.js b/packages/@jsonql/ws/src/node.js index fbe51c89..7f6994d8 100644 --- a/packages/@jsonql/ws/src/node.js +++ b/packages/@jsonql/ws/src/node.js @@ -1,10 +1,10 @@ // this is the module entry point for node -import { jsonqlWsClientCore } from 'jsonql-ws-client-core' +import { wsClientCore } from 'jsonql-ws-client-core' import { wsClientAppProps, wsClientConstProps } from './options' import wsClientResolver from './node-ws-client-resolver' // export back the function and that's it export default function wsBrowserClient(config = {}, constProps = {}) { - const initMethod = jsonqlWsClientCore(wsClientResolver, wsClientAppProps, Object.assign(wsClientConstProps, constProps)) + const initMethod = wsClientCore(wsClientResolver, wsClientAppProps, Object.assign(wsClientConstProps, constProps)) return initMethod(config) } -- Gitee From 61d56119affbe18eca65679aa2d127981b0f3e11 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 17:24:08 +0800 Subject: [PATCH 12/26] keep the working version the new one is not working --- packages/@jsonql/ws/{node.js => node-org.js} | 0 packages/@jsonql/ws/{node.js.map => node-org.js.map} | 0 packages/@jsonql/ws/tests/ws-client-auth-login.test.js | 2 +- packages/@jsonql/ws/tests/ws-client-auth.test.js | 2 +- packages/@jsonql/ws/tests/ws-client-basic.test.js | 2 +- packages/@jsonql/ws/tests/ws-client-chain.test.js | 10 +++++----- 6 files changed, 8 insertions(+), 8 deletions(-) rename packages/@jsonql/ws/{node.js => node-org.js} (100%) rename packages/@jsonql/ws/{node.js.map => node-org.js.map} (100%) diff --git a/packages/@jsonql/ws/node.js b/packages/@jsonql/ws/node-org.js similarity index 100% rename from packages/@jsonql/ws/node.js rename to packages/@jsonql/ws/node-org.js diff --git a/packages/@jsonql/ws/node.js.map b/packages/@jsonql/ws/node-org.js.map similarity index 100% rename from packages/@jsonql/ws/node.js.map rename to packages/@jsonql/ws/node-org.js.map 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 c3f14a4b..2ddc0278 100644 --- a/packages/@jsonql/ws/tests/ws-client-auth-login.test.js +++ b/packages/@jsonql/ws/tests/ws-client-auth-login.test.js @@ -3,7 +3,7 @@ const test = require('ava') const { join } = require('path') const fsx = require('fs-extra') // -const wsClient = require('../node') +const wsClient = require('../main') const serverSetup = require('./fixtures/server-setup') const genToken = require('./fixtures/token') diff --git a/packages/@jsonql/ws/tests/ws-client-auth.test.js b/packages/@jsonql/ws/tests/ws-client-auth.test.js index 51d7231e..4837e9e9 100644 --- a/packages/@jsonql/ws/tests/ws-client-auth.test.js +++ b/packages/@jsonql/ws/tests/ws-client-auth.test.js @@ -1,7 +1,7 @@ // standard ws client test without auth const test = require('ava') -const wsClient = require('../node') +const wsClient = require('../main') const serverSetup = require('./fixtures/server-setup') const { join } = require('path') diff --git a/packages/@jsonql/ws/tests/ws-client-basic.test.js b/packages/@jsonql/ws/tests/ws-client-basic.test.js index 1b46f5f8..a3eae5da 100644 --- a/packages/@jsonql/ws/tests/ws-client-basic.test.js +++ b/packages/@jsonql/ws/tests/ws-client-basic.test.js @@ -4,7 +4,7 @@ const { join } = require('path') const fsx = require('fs-extra') const { JS_WS_NAME } = require('jsonql-constants') -const wsClient = require('../node') +const wsClient = require('../main') const serverSetup = require('./fixtures/server-setup') const contractDir = join(__dirname, 'fixtures', 'contract') diff --git a/packages/@jsonql/ws/tests/ws-client-chain.test.js b/packages/@jsonql/ws/tests/ws-client-chain.test.js index 252e536b..9da193c2 100644 --- a/packages/@jsonql/ws/tests/ws-client-chain.test.js +++ b/packages/@jsonql/ws/tests/ws-client-chain.test.js @@ -14,16 +14,16 @@ 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 publicContract = fsx.readJsonSync(join(contractDir, 'public-contract.json')) +// const { NOT_LOGIN_ERR_MSG } = require('jsonql-constants') -const payload = {name: 'Joel'}; +const payload = {name: 'Joel'} const token = genToken(payload) -const debug = require('debug')('jsonql-ws-client:test:ws-client-chain') +// const debug = require('debug')('jsonql-ws-client:test:ws-client-chain') -const port = 8004; +const port = 8004 test.before(async t => { const { io, app } = await serverSetup({ -- Gitee From 78364f63cf359c9d978c6a31b0a1ebc38c52e350 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 19:05:27 +0800 Subject: [PATCH 13/26] moving things around and abandon the callback feature --- packages/@jsonql/ws/main.js | 8031 ++++++++++++++++- packages/@jsonql/ws/main.js.map | 2 +- packages/@jsonql/ws/package.json | 5 +- .../@jsonql/ws/tests/log/auth-test-fail.log | 60 + packages/@jsonql/ws/tests/log/auth-test.log | 466 + .../@jsonql/ws/tests/ws-client-auth.test.js | 4 +- .../ws-client-core/src/core/action-call.js | 20 +- .../src/core/cb/callback-handler.js | 34 + .../src/core/{ => cb}/setup-callback-api.js | 0 .../src/core/resolver-methods.js | 49 +- 10 files changed, 8615 insertions(+), 56 deletions(-) create mode 100644 packages/@jsonql/ws/tests/log/auth-test-fail.log create mode 100644 packages/@jsonql/ws/tests/log/auth-test.log create mode 100644 packages/ws-client-core/src/core/cb/callback-handler.js rename packages/ws-client-core/src/core/{ => cb}/setup-callback-api.js (100%) diff --git a/packages/@jsonql/ws/main.js b/packages/@jsonql/ws/main.js index c3cf670b..8b447e30 100644 --- a/packages/@jsonql/ws/main.js +++ b/packages/@jsonql/ws/main.js @@ -1,2 +1,8031 @@ -"use strict";var t,r=(t=require("ws"))&&"object"==typeof t&&"default"in t?t.default:t,e=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 406},e.name.get=function(){return"Jsonql406Error"},Object.defineProperties(r,e),r}(Error),n=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 500},e.name.get=function(){return"Jsonql500Error"},Object.defineProperties(r,e),r}(Error),o=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 403},e.name.get=function(){return"JsonqlForbiddenError"},Object.defineProperties(r,e),r}(Error),a=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 401},e.name.get=function(){return"JsonqlAuthorisationError"},Object.defineProperties(r,e),r}(Error),i=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 401},e.name.get=function(){return"JsonqlContractAuthError"},Object.defineProperties(r,e),r}(Error),u=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 500},e.name.get=function(){return"JsonqlResolverAppError"},Object.defineProperties(r,e),r}(Error),c=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 404},e.name.get=function(){return"JsonqlResolverNotFoundError"},Object.defineProperties(r,e),r}(Error),s=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlEnumError"},Object.defineProperties(r,e),r}(Error),f=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlTypeError"},Object.defineProperties(r,e),r}(Error),l=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlCheckerError"},Object.defineProperties(r,e),r}(Error),p=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(r,e),r}(Error),h=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0},statusCode:{configurable:!0}};return e.name.get=function(){return"JsonqlError"},e.statusCode.get=function(){return-1},Object.defineProperties(r,e),r}(Error),v=function(t){function r(e,n){t.call(this,n),this.statusCode=e,this.className=r.name}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlServerError"},Object.defineProperties(r,e),r}(Error);function g(t){if(Array.isArray(t))throw new p("",t);var r=t.message||"No message",g=t.detail||t;switch(!0){case t instanceof e:throw new e(r,g);case t instanceof n:throw new n(r,g);case t instanceof o:throw new o(r,g);case t instanceof a:throw new a(r,g);case t instanceof i:throw new i(r,g);case t instanceof u:throw new u(r,g);case t instanceof c:throw new c(r,g);case t instanceof s:throw new s(r,g);case t instanceof f:throw new f(r,g);case t instanceof l:throw new l(r,g);case t instanceof p:throw new p(r,g);case t instanceof v:throw new v(r,g);default:throw new h(r,g)}}var y="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},d="object"==typeof y&&y&&y.Object===Object&&y,b="object"==typeof self&&self&&self.Object===Object&&self,_=d||b||Function("return this")(),m=_.Symbol;function w(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 a=Array(o);++n-1;);return e}(n,o),function(t,r){for(var e=t.length;e--&&M(r,t[e],0)>-1;);return e}(n,o)+1).join("")}var Z=function(t){return!!j(t)||null!=t&&""!==X(t)};function tt(t){return function(t){return"number"==typeof t||P(t)&&"[object Number]"==A(t)}(t)&&t!=+t}function rt(t){return"string"==typeof t||!j(t)&&P(t)&&"[object String]"==A(t)}var et=function(t){return!rt(t)&&!tt(parseFloat(t))},nt=function(t){return""!==X(t)&&rt(t)},ot=function(t){return null!=t&&"boolean"==typeof t},at=function(t,r){return void 0===r&&(r=!0),void 0!==t&&""!==t&&""!==X(t)&&(!1===r||!0===r&&null!==t)},it=function(t){switch(t){case"number":return et;case"string":return nt;case"boolean":return ot;default:return at}},ut=function(t,r){return void 0===r&&(r=""),!!j(t)&&(""===r||""===X(r)||!(t.filter((function(t){return!it(r)(t)})).length>0))},ct=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var r=t.replace("array.<","").replace(">","");return r.indexOf("|")?r.split("|"):[r]}return!1},st=function(t,r){var e=t.arg;return r.length>1?!e.filter((function(t){return!(r.length>r.filter((function(r){return!it(r)(t)})).length)})).length:r.length>r.filter((function(t){return!ut(e,t)})).length};function ft(t,r){return function(e){return t(r(e))}}var lt=ft(Object.getPrototypeOf,Object),pt=Function.prototype,ht=Object.prototype,vt=pt.toString,gt=ht.hasOwnProperty,yt=vt.call(Object);function dt(t){if(!P(t)||"[object Object]"!=A(t))return!1;var r=lt(t);if(null===r)return!0;var e=gt.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&vt.call(e)==yt}var bt,_t=function(t,r,e){for(var n=-1,o=Object(t),a=e(t),i=a.length;i--;){var u=a[bt?i:++n];if(!1===r(o[u],u,o))break}return t};function mt(t){return P(t)&&"[object Arguments]"==A(t)}var wt=Object.prototype,jt=wt.hasOwnProperty,Ot=wt.propertyIsEnumerable,St=mt(function(){return arguments}())?mt:function(t){return P(t)&&jt.call(t,"callee")&&!Ot.call(t,"callee")};var kt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Et=kt&&"object"==typeof module&&module&&!module.nodeType&&module,$t=Et&&Et.exports===kt?_.Buffer:void 0,Tt=($t?$t.isBuffer:void 0)||function(){return!1},At=/^(?:0|[1-9]\d*)$/;function Pt(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&At.test(t))&&t>-1&&t%1==0&&t-1&&t%1==0&&t<=9007199254740991}var zt={};zt["[object Float32Array]"]=zt["[object Float64Array]"]=zt["[object Int8Array]"]=zt["[object Int16Array]"]=zt["[object Int32Array]"]=zt["[object Uint8Array]"]=zt["[object Uint8ClampedArray]"]=zt["[object Uint16Array]"]=zt["[object Uint32Array]"]=!0,zt["[object Arguments]"]=zt["[object Array]"]=zt["[object ArrayBuffer]"]=zt["[object Boolean]"]=zt["[object DataView]"]=zt["[object Date]"]=zt["[object Error]"]=zt["[object Function]"]=zt["[object Map]"]=zt["[object Number]"]=zt["[object Object]"]=zt["[object RegExp]"]=zt["[object Set]"]=zt["[object String]"]=zt["[object WeakMap]"]=!1;var Ct,xt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Rt=xt&&"object"==typeof module&&module&&!module.nodeType&&module,qt=Rt&&Rt.exports===xt&&d.process,Mt=function(){try{var t=Rt&&Rt.require&&Rt.require("util").types;return t||qt&&qt.binding&&qt.binding("util")}catch(t){}}(),Ft=Mt&&Mt.isTypedArray,Lt=Ft?(Ct=Ft,function(t){return Ct(t)}):function(t){return P(t)&&Nt(t.length)&&!!zt[A(t)]},Jt=Object.prototype.hasOwnProperty;function It(t,r){var e=j(t),n=!e&&St(t),o=!e&&!n&&Tt(t),a=!e&&!n&&!o&&Lt(t),i=e||n||o||a,u=i?function(t,r){for(var e=-1,n=Array(t);++e-1},tr.prototype.set=function(t,r){var e=this.__data__,n=Xt(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};var rr,er=_["__core-js_shared__"],nr=(rr=/[^.]+$/.exec(er&&er.keys&&er.keys.IE_PROTO||""))?"Symbol(src)_1."+rr:"";var or=Function.prototype.toString;function ar(t){if(null!=t){try{return or.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var ir=/^\[object .+?Constructor\]$/,ur=Function.prototype,cr=Object.prototype,sr=ur.toString,fr=cr.hasOwnProperty,lr=RegExp("^"+sr.call(fr).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pr(t){return!(!Bt(t)||function(t){return!!nr&&nr in t}(t))&&(Wt(t)?lr:ir).test(ar(t))}function hr(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pr(e)?e:void 0}var vr=hr(_,"Map"),gr=hr(Object,"create");var yr=Object.prototype.hasOwnProperty;var dr=Object.prototype.hasOwnProperty;function br(t){var r=-1,e=null==t?0:t.length;for(this.clear();++ru))return!1;var s=a.get(t);if(s&&a.get(r))return s==r;var f=-1,l=!0,p=2&e?new jr:void 0;for(a.set(t,r),a.set(r,t);++fr.type.filter((function(t){var r;return void 0===e||(!1!==(r=ct(t))?!st({arg:e},r):!it(t)(e))})).length)})).length}return!1},be=function(t,r){var e,n,o,a,i;switch(!0){case"object"===t:return o=(n=r).arg,a=n.param,i=[o],Array.isArray(a.keys)&&a.keys.length&&i.push(a.keys),!Reflect.apply(de,null,i);case"array"===t:return!ut(r.arg);case!1!==(e=ct(t)):return!st(r,e);default:return!it(t)(r.arg)}},_e=function(t,r){return void 0!==t?t:!0===r.optional&&void 0!==r.defaultvalue?r.defaultvalue:null},me=function(t,r,e){var n;void 0===e&&(e=!1);var o=function(t,r){if(!ut(r))throw new h("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===r.length)return[];if(!ut(t))throw new h("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==r.length:return t.map((function(t,e){return{arg:t,index:e,param:r[e]}}));case!0===r[0].variable:var e=r[0].type;return t.map((function(t,n){return{arg:t,index:n,param:r[n]||{type:e,name:"_"}}}));case t.lengthr.length:var n=r.length,o=["any"];return t.map((function(t,e){var a=e>=n||!!r[e].optional,i=r[e]||{type:o,name:"_"+e};return{arg:a?_e(t,i):t,index:e,param:i,optional:a}}));default:throw new h("Could not understand your arguments and parameter structure!",{args:t,params:r})}}(t,r),a=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var r=t.arg,e=t.param;return!!Z(r)&&!(e.type.length>e.type.filter((function(r){return be(r,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(r){return be(r,t)})).length)}));return e?((n={}).error=a,n.data=o.map((function(t){return t.arg})),n):a},we=function(){try{var t=hr(Object,"defineProperty");return t({},"",{}),t}catch(t){}}();function je(t,r,e){"__proto__"==r&&we?we(t,r,{configurable:!0,enumerable:!0,value:e,writable:!0}):t[r]=e}function Oe(t,r,e){(void 0===e||Qt(t[r],e))&&(void 0!==e||r in t)||je(t,r,e)}var Se="object"==typeof exports&&exports&&!exports.nodeType&&exports,ke=Se&&"object"==typeof module&&module&&!module.nodeType&&module,Ee=ke&&ke.exports===Se?_.Buffer:void 0,$e=Ee?Ee.allocUnsafe:void 0;function Te(t,r){var e,n,o=r?(e=t.buffer,n=new e.constructor(e.byteLength),new kr(n).set(new kr(e)),n):t.buffer;return new t.constructor(o,t.byteOffset,t.length)}var Ae=Object.create,Pe=function(){function t(){}return function(r){if(!Bt(r))return{};if(Ae)return Ae(r);t.prototype=r;var e=new t;return t.prototype=void 0,e}}();function Ne(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var ze=Object.prototype.hasOwnProperty;function Ce(t,r,e){var n=t[r];ze.call(t,r)&&Qt(n,e)&&(void 0!==e||r in t)||je(t,r,e)}var xe=Object.prototype.hasOwnProperty;function Re(t){if(!Bt(t))return function(t){var r=[];if(null!=t)for(var e in Object(t))r.push(e);return r}(t);var r=Dt(t),e=[];for(var n in t)("constructor"!=n||!r&&xe.call(t,n))&&e.push(n);return e}function qe(t){return Yt(t)?It(t,!0):Re(t)}function Me(t){return function(t,r,e,n){var o=!e;e||(e={});for(var a=-1,i=r.length;++a0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(Ue);function Ve(t,r){return He(function(t,r,e){return r=Ie(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,a=Ie(n.length-r,0),i=Array(a);++o1?r[n-1]:void 0,a=n>2?r[2]:void 0;for(o=Be.length>3&&"function"==typeof o?(n--,o):void 0,a&&function(t,r,e){if(!Bt(e))return!1;var n=typeof r;return!!("number"==n?Yt(e)&&Pt(r,e.length):"string"==n&&r in e)&&Qt(e[r],t)}(r[0],r[1],a)&&(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,ln(t))}),Reflect.apply(t,null,e))}};function yn(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))}}function dn(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}function bn(t,r,e,n){void 0===n&&(n=!1);var o=function(t,r){var e=Object.getOwnPropertyDescriptor(t,r);return void 0!==e&&e.value?e.value:e}(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t}function _n(t){return!!pn(t,"socket")&&t.socket}var mn=function(t){void 0===t&&(t=!1);var r=Date.now();return t?Math.floor(r/1e3):r};function wn(t,r,e){if(void 0===r&&(r=[]),void 0===e&&(e=!1),rt(t)&&j(r)){var n=function(t){var r;return(r={}).args=t,r}(r);return!0===e?n:function(t,r){var e;return(e={})[t]=r,e.TS=[mn()],e}(t,n)}throw new p("[createQuery] expect resolverName to be string and args to be array!",{resolverName:t,args:r})}var jn=new WeakMap,On=new WeakMap;var Sn=function(){this.__suspend__=null,this.queueStore=new Set},kn={$suspend:{configurable:!0},$queues:{configurable:!0}};kn.$suspend.set=function(t){var r=this;if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value!");var e=this.__suspend__;this.__suspend__=t,this.logger("($suspend)","Change from "+e+" --\x3e "+t),!0===e&&!1===t&&setTimeout((function(){r.release()}),1)},Sn.prototype.$queue=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return!0===this.__suspend__&&(this.logger("($queue)","added to $queue",t),this.queueStore.add(t)),this.__suspend__},kn.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},Sn.prototype.release=function(){var t=this,r=this.queueStore.size;if(this.logger("(release)","Release was called "+r),r>0){var e=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",e),e.forEach((function(r){t.logger(r),Reflect.apply(t.$trigger,t,r)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(Sn.prototype,kn);var En=function(t){function r(r){if("function"!=typeof r)throw new Error("Just die here the logger is not a function!");t.call(this,{logger:r})}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(r.prototype,e),r}(function(t){function r(r){void 0===r&&(r={}),t.call(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={$done:{configurable:!0}};return r.prototype.logger=function(){},r.prototype.$on=function(t,r,e){var n=this;void 0===e&&(e=null);this.validate(t,r);var o=this.takeFromStore(t);if(!1===o)return this.logger("($on)",t+" callback is not in lazy store"),this.addToNormalStore(t,"on",r,e);this.logger("($on)",t+" found in lazy store");var a=0;return o.forEach((function(o){var i=o[0],u=o[1],c=o[2];if(c&&"on"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);n.logger("($on)","call run on "+t),n.run(r,i,e||u),a+=n.addToNormalStore(t,"on",r,e||u)})),a},r.prototype.$once=function(t,r,e){void 0===e&&(e=null),this.validate(t,r);var n=this.takeFromStore(t);this.normalStore;if(!1===n)return this.logger("($once)",t+" not in the lazy store"),this.addToNormalStore(t,"once",r,e);this.logger("($once)",n);var o=Array.from(n)[0],a=o[0],i=o[1],u=o[2];if(u&&"once"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);this.logger("($once)","call run for "+t),this.run(r,a,e||i),this.$off(t)},r.prototype.$only=function(t,r,e){var n=this;void 0===e&&(e=null),this.validate(t,r);var o=!1,a=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger("($only)",t+" add to store"),o=this.addToNormalStore(t,"only",r,e)),!1!==a)&&(this.logger("($only)",t+" found data in lazy store to execute"),Array.from(a).forEach((function(o){var a=o[0],i=o[1],u=o[2];if(u&&"only"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);n.logger("($only)","call run for "+t),n.run(r,a,e||i)})));return o},r.prototype.$onlyOnce=function(t,r,e){void 0===e&&(e=null),this.validate(t,r);var n=!1,o=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger("($onlyOnce)",t+" add to store"),n=this.addToNormalStore(t,"onlyOnce",r,e)),!1!==o){this.logger("($onlyOnce)",o);var a=Array.from(o)[0],i=a[0],u=a[1],c=a[2];if(c&&"onlyOnce"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);this.logger("($onlyOnce)","call run for "+t),this.run(r,i,e||u),this.$off(t)}return n},r.prototype.$replace=function(t,r,e,n){if(void 0===e&&(e=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,r),Reflect.apply(o,this,[t,r,e])}throw new Error(n+" is not supported!")},r.prototype.$trigger=function(t,r,e,n){void 0===r&&(r=[]),void 0===e&&(e=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,a=this.normalStore;if(this.logger("($trigger)","normalStore",a),a.has(t)){var i=this.$queue(t,r,e,n);if(this.logger("($trigger)",t,"found; add to queue: ",i),!0===i)return this.logger("($trigger)",t,"not executed. Exit now."),!1;for(var u=Array.from(a.get(t)),c=u.length,s=!1,f=0;f0;)n[o]=arguments[o+2];if(t.has(r)?(this.logger("(addToStore)",r+" existed"),e=t.get(r)):(this.logger("(addToStore)","create new Set for "+r),e=new Set),n.length>2)if(Array.isArray(n[0])){var a=n[2];this.checkTypeInLazyStore(r,a)||e.add(n)}else this.checkContentExist(n,e)||(this.logger("(addToStore)","insert new",n),e.add(n));else e.add(n);return t.set(r,e),[t,e.size]},r.prototype.checkContentExist=function(t,r){return!!Array.from(r).filter((function(r){return r[0]===t[0]})).length},r.prototype.checkTypeInStore=function(t,r){this.validateEvt(t,r);var e=this.$get(t,!0);return!1===e||!e.filter((function(t){var e=t[3];return r!==e})).length},r.prototype.checkTypeInLazyStore=function(t,r){this.validateEvt(t,r);var e=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",e),!!e&&!!Array.from(e).filter((function(t){return t[2]!==r})).length},r.prototype.addToNormalStore=function(t,r,e,n){if(void 0===n&&(n=null),this.logger("(addToNormalStore)",t,r,"try to add to normal store"),this.checkTypeInStore(t,r)){this.logger("(addToNormalStore)",r+" can add to "+t+" normal store");var o=this.hashFnToKey(e),a=[this.normalStore,t,o,e,n,r],i=Reflect.apply(this.addToStore,this,a),u=i[0],c=i[1];return this.normalStore=u,c}return!1},r.prototype.addToLazyStore=function(t,r,e,n){void 0===r&&(r=[]),void 0===e&&(e=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(r),e];n&&o.push(n);var a=Reflect.apply(this.addToStore,this,o),i=a[0],u=a[1];return this.lazyStore=i,u},r.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},e.normalStore.set=function(t){jn.set(this,t)},e.normalStore.get=function(){return jn.get(this)},e.lazyStore.set=function(t){On.set(this,t)},e.lazyStore.get=function(){return On.get(this)},r.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,r){return(t=(t<<5)-t+r.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(r.prototype,e),r}(Sn)));function $n(t){var r,e,n=t.contract;return t.enableAuth?function(t,r){void 0===r&&(r=!1);var e=_n(t);if(!1===e){if(r)return t;throw new h("socket not found in contract!")}var n,o={},a=0;for(var i in e){var u=e[i],c=u.namespace;c&&(o[c]||(++a,o[c]={}),o[c][i]=u,n||u.public&&(n=c))}return{size:a,nspSet:o,publicNamespace:n}}(n):((e={}).nspSet=((r={}).jsonql=function(t){var r=_n(t);if(!1!==r)return r;throw new c("Missing property in contract!")}(n),r),e.publicNamespace="jsonql",e)}var Tn=function(t,r){ln(r).forEach((function(r){t.$off(hn(r,"emit"))}))};function An(t,r,e){pn(t,"error")?e(t.error):pn(t,"data")?r(t.data):e({message:"UKNNOWN RESULT!",error:t})}function Pn(t,r,e,n,o){void 0===o&&(o=[]);var a=hn(r,"emit"),i=n?"result":"onResult";return t.$trigger(a,[e,ln(o)]),new Promise((function(n,o){t.$on(hn(r,e,i),(function(t){An(t,n,o)}))}))}var Nn=function(t,r,e,n,o,a){return dn(t,"send",(function(t){var i=a?"error":"onError";cn(ln(t),o.params,!0).then((function(o){if(!o.error||!o.error.length)return Pn(r,e,n,a,t);r.$call(hn(e,n,i),[new p(n,o.error)])})).catch((function(t){r.$call(hn(e,n,i),[new p(n,t)])}))}),(function(){return function(){for(var t=[],i=arguments.length;i--;)t[i]=arguments[i];return cn(t,o.params,!0).then((function(t){return Pn(r,e,n,a,t)})).catch(g)}}))};function zn(t,r,e,n,o){return[bn(t,"on",(function(t,o){if(un(t)&&vn(o))switch(t){case"result":r.$on(hn(e,n,"onResult"),(function(t){An(t,o,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}));break;case"message":r.$only(hn(e,n,"onMessage"),(function(t){An(t,o,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}));break;case"ready":r.$only(hn(e,n,"onError"),o);break;default:r.$trigger(hn(e,n,"onError"),new h(n,"Unknown event name "+t+"!"))}})),r,e,n,o]}var Cn=function(t,r,e,n,o,a){return[bn(t,"myNamespace",e),r,e,n,o,a]},xn=function(t,r,e,n,o,a){return[dn(t,"onResult",(function(t){vn(t)&&r.$on(hn(e,n,"onResult"),(function(o){An(o,t,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}))})),r,e,n,o,a]},Rn=function(t,r,e,n,o,a){return[dn(t,"onMessage",(function(t){if(vn(t)){r.$only(hn(e,n,"onMessage"),(function(o){An(o,t,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}))}})),r,e,n,o,a]},qn=function(t,r,e,n,o,a){return[dn(t,"onError",(function(t){vn(t)&&r.$only(hn(e,n,"onError"),t)})),r,e,n,o,a]};function Mn(t,r,e,n,o,a){var i=[Cn];a?i.push(zn):i.push(xn,Rn,qn),i.push(Nn);var u=Reflect.apply(gn,null,i);return Reflect.apply(u,null,[n,o,t,r,e,a])}function Fn(t,r,e,n,o){return function(){for(var a=[],i=arguments.length;i--;)a[i]=arguments[i];return cn(a,n.params,!0).then((function(n){return Pn(t,r,e,o,n)})).catch(g)}}var Ln,Jn,In=function(t,r,e){return[bn(t,e.loginHandlerName,(function(t){if(t&&un(t))return r.$trigger("__login__",[t]);throw new p(e.loginHandlerName,"Unexpected token "+t)})),r,e]},Un=function(t,r,e){return bn(t,e.logoutHandlerName,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__logout__",t)}))};function Dn(t,r,e){var n={},o=r.nspSet,a=t.useCallbackStyle;for(var i in o){var u=o[i];for(var c in u){var s=u[c];n=bn(n,c,Mn(i,c,s,Fn(e,i,c,s,a),e,a))}}return n.devHelpers={getNsp:function(){return Object.keys(o)},getVer:function(){return t.version||"NOT SET"}},Promise.resolve(n)}function Hn(t,r,e){var n=r.nspSet,o=t.useCallbackStyle,a=t.enableAuth,i=[Dn];return o?i.push((function(t){return function(t,r,e,n){return bn(t,"on",(function(t,n){if(un(t)&&vn(n))switch(t){case"error":for(var o in e)r.$on(hn(o,"error"),n);break;case"login":r.$only("login",n);break;case"ready":r.$on("ready",n);break;default:r.$trigger("error",new h("on","Unknown event name "+t+"!"))}}))}(t,e,n)})):(i.push((function(t){return function(t,r,e){return dn(t,"onError",(function(t){if(vn(t))for(var n in e)r.$on(hn(n,"onError"),t)}))}(t,e,n)}),(function(t){return function(t,r,e){return dn(t,"onReady",(function(t){vn(t)&&r.$on("onReady",t)}))}(t,e)})),a&&i.push((function(r){return function(t,r,e){return e.enableAuth?dn(t,"onLogin",(function(t){vn(t)&&r.$only("onLogin",t)})):t}(r,e,t)}))),a&&i.push((function(r){return function(t,r,e){return e.enableAuth?gn(In,Un)(t,r,e):t}(r,e,t)})),Reflect.apply(yn,null,i)(t,r,e)}var Vn=["roundtip","handshake"],Bn={useCallbackStyle:sn(!1,["boolean"]),loginHandlerName:sn("login",["string"]),logoutHandlerName:sn("logout",["string"]),loginMethod:sn("handshake",["string"],(Ln={},Ln.enumv=Vn,Ln)),useJwt:sn(!0,["boolean","string"]),authStrKey:sn(null,["string"]),hostname:sn(!1,["string"]),namespace:sn("jsonql",["string"]),wsOptions:sn({},["object"]),contract:sn({},["object"],(Jn={},Jn.checker=function(t){return!!function(t){return dt(t)&&(pn(t,"query")||pn(t,"mutation")||pn(t,"socket"))}(t)&&t},Jn)),enableAuth:sn(!1,["boolean"]),token:sn(!1,["string"])},Wn={eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:""};function Yn(t){return Promise.resolve(t).then((function(t){var r;return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new p(t)}}()),t.wssPath=(r=[t.hostname,t.namespace].join("/"),"ws"===t.serverType?r.replace("http://","ws://"):r),t}))}function Kn(t,r,e){return function(t,r,e){var n=Object.assign(Wn,e),o=Object.assign(Bn,r);return fn(t,o,n)}(t,r,e).then(Yn)}var Gn=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];Reflect.apply(console.info,console,["[jsonql-ws-client-core]"].concat(t))},Qn=function(t){var r=t.log,e=t.eventEmitter;return r("CHECKED_KEY",t.__checked__),e?(r("eventEmitter is:",e.name),e):(r("Create a new Event Emitter"),new En(t.log))},Xn=function(t){var r=t.log;return r&&"function"==typeof r||(t.log=Gn),t.log("--- wsClientCore config opts ---",t),t};function Zn(t,r,e){return void 0===r&&(r={}),void 0===e&&(e={}),function(n){return void 0===n&&(n={}),Kn(n,r,e).then((function(r){return function(t,r){return Promise.resolve(r).then(Xn).then((function(t){return{opts:t,nspMap:$n(t),ee:Qn(t)}})).then((function(r){var e=r.opts,n=r.nspMap,o=r.ee;return t(e,n,o)})).then((function(t){return Hn(t.opts,t.nspMap,t.ee)})).catch((function(t){console.error("jsonql-ws-core-client init error",t)}))}(t,r)}))}}var to={version:"version: 1.1.0 module: cjs",serverType:"ws"},ro={},eo=function(t){var r=t.toLowerCase();return r.indexOf("http")>-1?r.indexOf("https")>-1?r.replace("https","wss"):r.replace("http","ws"):r};function no(t,r){return void 0===r&&(r=!1),!1===r?function(r){return new t(eo(r))}:function(r,e){var n=eo(r),o=e&&"string"==typeof e?n+"?token="+e:n;try{return new t(o)}catch(t){return console.error("WebSocket Connection Error",t),!1}}}function oo(t,r){var e=r.hostname,n=r.wssPath,o=r.wsOptions;return(0,r.nspClient)(t?[e,t].join("/"):n,o)}var ao=function(t,r,e){var n=e.useCallbackStyle,o=e.log,a=n?"error":"onError",i=n?"result":"onResult";r.$only(hn(t,"emit"),(function(e,n){o("[notLoginHandler] hijack the ws call",t,e,n);var u={message:"NOT LOGIN"};r.$call(hn(t,e,a),[u]),r.$call(hn(t,e,i),[{error:u}])}))};function io(t,r,e,n,o,a){var i=function(t){return t.length>1&&t[0]}(o),u=!1,c=t.log;o.forEach((function(o){if(u=i===o,a[o]){c("[call bindWsHandler]",u,o);var s=[o,a[o],e,u,t];if("socket.io"===t.serverType){var f=r.nspSet;s.push(f[o])}Reflect.apply(n,null,s)}else ao(o,e,t)})),e.$on("__logout__",(function(){c("LOGOUT_EVENT_NAME"),function(t,r,e,n){void 0===n&&(n={});var o=n.useCallbackStyle?"error":"onError";r.forEach((function(r){t.$call(hn(r,o),[{message:e,namespace:r}])}))}(e,o,"__logout__"),o.forEach((function(r){Tn(e,r),a[r]=!1,ao(r,e,t)}))}))}var uo=["__reply__","__event__","__data__"],co=function(t){var r,e=t.data;if(!1!==(r=function(t){var r=t.data;return!!r&&(uo.filter((function(t){return pn(r,t)})).length===uo.length&&r)}(un(e)?JSON.parse(e):e)))return{resolverName:r.__event__,data:r.__data__,type:r.__reply__};throw new h("payload can not be decoded",t)},so=function(t,r,e,n,o){var a=[r];e&&a.push(e),a.push(o);var i=Reflect.apply(hn,null,a),u=n.data||n;t.$trigger(i,[u])};function fo(t,r,e,n,o){var a=o.useCallbackStyle,i=o.log;i("wsMainHandler log test");var u=a?"ready":"onReady",c=a?"login":"onLogin",s=a?"message":"onMessage",f=a?"result":"onResult",l=a?"error":"onError";r.onopen=function(){i("ws.onopen listened"),e.$call(u,t),n&&(i("isPrivate and fire the "+c),e.$call(c,t)),e.$only(hn(t,"emit"),(function(t,e){i("calling server",t,e),r.send(function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(wn(t,r,e))}(t,e))}))},r.onmessage=function(r){try{var n=co(r),o=n.resolverName,a=n.type;switch(i("Hear from server",a,n),a){case"emit":var u=hn(t,o,s),c=e.$trigger(u,[n]);i("EMIT_REPLY_TYPE",u,c);break;case"acknowledge":var p=hn(t,o,f);e.$trigger(p,[n]);break;case"error":i("ERROR_TYPE"),so(e,t,o,n,l);break;default:i("Unhandled event!",n),so(e,t,o,n,l)}}catch(r){console.error("ws.onmessage error",r),so(e,t,!1,r,l)}},r.onclose=function(){i("ws.onclose callback")},e.$on("__logout__",(function(){try{i("terminate ws connection"),r.terminate()}catch(t){console.error("ws.terminate error",t)}}))}var lo=function(t,r,e){var n,o=r.nspSet,a=r.publicNamespace,i=!1,u=[],c={};if(t.enableAuth)i=!0,c=(u=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e}(o,a)).map((function(r,n){var o,a,i;return 0===n?e?(t.token=e,(o={})[r]=function(t,r){var e=r.hostname,n=r.wssPath,o=r.token,a=r.wsOptions,i=r.nspAuthClient,u=t?[e,t].join("/"):n;if(o&&"string"!=typeof o)throw new Error("Expect token to be string, but got "+o);return i(u,o,a)}(r,t),o):((a={})[r]=!1,a):((i={})[r]=oo(r,t),i)})).reduce((function(t,r){return Object.assign(t,r)}),{});else{var s=(n=o,Object.keys(n)[0]);u.push(s),c[s]=oo(!1,t)}return{nsps:c,namespaces:u,login:i}};var po,ho,vo,go=(ho=no(po=r),vo=no(po,!0),function(t,r,e){t.nspClient=ho,t.nspAuthClient=vo;var n=t.log;return n&&"function"==typeof n&&(n("@jsonql/ws ee",e.name),n("@jsonql/ws createClientResolver",t)),function(t,r,e){var n=[t,r,e,fo],o=t.token,a=t.log,i=lo(t,r,o),u=i.nsps,c=i.namespaces,s=i.login;return Reflect.apply(io,null,n.concat([c,u])),s&&e.$only("__login__",(function(o){a("createClient LOGIN_EVENT_NAME"),Tn(e,c);var i=lo(t,r,o);Reflect.apply(io,null,n.concat([i.namespaces,i.nsps]))})),{opts:t,nspMap:r,ee:e}}(t,r,e)});module.exports=function(t,r){return void 0===t&&(t={}),void 0===r&&(r={}),Zn(go,ro,Object.assign(to,r))(t)}; +'use strict'; + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var WebSocket = _interopDefault(require('ws')); + +/** + * 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? + */ +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; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, Jsonql406Error); + } + } + + 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 406; + }; + + staticAccessors.name.get = function () { + return 'Jsonql406Error'; + }; + + Object.defineProperties( Jsonql406Error, staticAccessors ); + + return Jsonql406Error; +}(Error)); + +/** + * 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? + */ +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; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, Jsonql500Error); + } + } + + 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 500; + }; + + staticAccessors.name.get = function () { + return 'Jsonql500Error'; + }; + + Object.defineProperties( Jsonql500Error, staticAccessors ); + + return Jsonql500Error; +}(Error)); + +/** + * 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? + */ +var JsonqlForbiddenError = /*@__PURE__*/(function (Error) { + function JsonqlForbiddenError() { + 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 = JsonqlForbiddenError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlForbiddenError); + } + } + + if ( Error ) JsonqlForbiddenError.__proto__ = Error; + JsonqlForbiddenError.prototype = Object.create( Error && Error.prototype ); + JsonqlForbiddenError.prototype.constructor = JsonqlForbiddenError; + + var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; + + staticAccessors.statusCode.get = function () { + return 403; + }; + + staticAccessors.name.get = function () { + return 'JsonqlForbiddenError'; + }; + + Object.defineProperties( JsonqlForbiddenError, staticAccessors ); + + return JsonqlForbiddenError; +}(Error)); + +/** + * 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? + */ +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); + } + } + + 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 401; + }; + + staticAccessors.name.get = function () { + return 'JsonqlAuthorisationError'; + }; + + Object.defineProperties( JsonqlAuthorisationError, staticAccessors ); + + return JsonqlAuthorisationError; +}(Error)); + +/** + * 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? + */ +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]; + + this.className = JsonqlContractAuthError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlContractAuthError); + } + } + + 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 401; + }; + + staticAccessors.name.get = function () { + return 'JsonqlContractAuthError'; + }; + + Object.defineProperties( JsonqlContractAuthError, staticAccessors ); + + return JsonqlContractAuthError; +}(Error)); + +/** + * 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? + */ +var JsonqlResolverAppError = /*@__PURE__*/(function (Error) { + function JsonqlResolverAppError() { + 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 = JsonqlResolverAppError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlResolverAppError); + } + } + + 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 500; + }; + + staticAccessors.name.get = function () { + return 'JsonqlResolverAppError'; + }; + + Object.defineProperties( JsonqlResolverAppError, staticAccessors ); + + return JsonqlResolverAppError; +}(Error)); + +/** + * 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? + */ +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; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlResolverNotFoundError); + } + } + + 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 404; + }; + + staticAccessors.name.get = function () { + return 'JsonqlResolverNotFoundError'; + }; + + Object.defineProperties( JsonqlResolverNotFoundError, staticAccessors ); + + return JsonqlResolverNotFoundError; +}(Error)); + +// 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); + } + } + + 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 ( 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 ( 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)); + +// 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); + + this.message = args[0]; + this.detail = args[1]; + + this.className = JsonqlValidationError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlValidationError); + } + } + + if ( Error ) JsonqlValidationError.__proto__ = Error; + JsonqlValidationError.prototype = Object.create( Error && Error.prototype ); + JsonqlValidationError.prototype.constructor = JsonqlValidationError; + + var staticAccessors = { name: { configurable: true } }; + + staticAccessors.name.get = function () { + return 'JsonqlValidationError'; + }; + + Object.defineProperties( JsonqlValidationError, staticAccessors ); + + return JsonqlValidationError; +}(Error)); + +// 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 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 CHECKED_KEY = '__checked__'; +var LOGIN_NAME = 'login'; +var ISSUER_NAME = LOGIN_NAME; // legacy issue need to replace them later +var LOGOUT_NAME = 'logout'; + +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 = '>'; + +var NO_ERROR_MSG = 'No message'; +var NO_STATUS_CODE = -1; +var LOGIN_EVENT_NAME = '__login__'; +var LOGOUT_EVENT_NAME = '__logout__'; + +// for ws servers +var WS_REPLY_TYPE = '__reply__'; +var WS_EVT_NAME = '__event__'; +var WS_DATA_NAME = '__data__'; +var EMIT_REPLY_TYPE = 'emit'; +var ACKNOWLEDGE_REPLY_TYPE = 'acknowledge'; +var ERROR_TYPE = 'error'; + +var NSP_SET = 'nspSet'; +var PUBLIC_NAMESPACE = 'publicNamespace'; + +var JS_WS_SOCKET_IO_NAME = 'socket.io'; +var JS_WS_NAME = 'ws'; + +// for ws client +var ON_MESSAGE_PROP_NAME = 'onMessage'; +var ON_RESULT_PROP_NAME = 'onResult'; +var ON_ERROR_PROP_NAME = 'onError'; +var ON_READY_PROP_NAME = 'onReady'; +var ON_LOGIN_PROP_NAME = 'onLogin'; // new @1.8.6 + +var SEND_MSG_PROP_NAME = 'send'; +// breaking change from 1.8.8 the above name was the name below +// the names are using in the new resolver.on getter interface +var MESSAGE_PROP_NAME = 'message'; +var RESULT_PROP_NAME = 'result'; +var ERROR_PROP_NAME = 'error'; +var READY_PROP_NAME = 'ready'; +var LOGIN_PROP_NAME = 'login'; // new @1.8.6 +var NOT_LOGIN_ERR_MSG = 'NOT LOGIN'; +var TOKEN_PARAM_NAME = 'token'; +var IO_ROUNDTRIP_LOGIN = 'roundtip'; +var IO_HANDSHAKE_LOGIN = 'handshake'; + +/** + * 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 = /*@__PURE__*/(function (Error) { + function JsonqlError() { + 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 = JsonqlError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlError); + // this.detail = this.stack; + } + } + + if ( Error ) JsonqlError.__proto__ = Error; + JsonqlError.prototype = Object.create( Error && Error.prototype ); + JsonqlError.prototype.constructor = JsonqlError; + + var staticAccessors = { name: { configurable: true },statusCode: { configurable: true } }; + + staticAccessors.name.get = function () { + return 'JsonqlError'; + }; + + staticAccessors.statusCode.get = function () { + return NO_STATUS_CODE; + }; + + Object.defineProperties( JsonqlError, staticAccessors ); + + return JsonqlError; +}(Error)); + +// 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; + } + + if ( Error ) JsonqlServerError.__proto__ = Error; + JsonqlServerError.prototype = Object.create( Error && Error.prototype ); + JsonqlServerError.prototype.constructor = JsonqlServerError; + + var staticAccessors = { name: { configurable: true } }; + + staticAccessors.name.get = function () { + return 'JsonqlServerError'; + }; + + 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 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(msg, detail) + } +} + +// constants + +var SOCKET_IO = JS_WS_SOCKET_IO_NAME; + +var MISSING_PROP_ERR = 'Missing property in contract!'; + +var EMIT_EVT = EMIT_REPLY_TYPE; + +var UNKNOWN_RESULT = 'UKNNOWN RESULT!'; + +var MY_NAMESPACE = 'myNamespace'; + +var CB_FN_NAME = 'on'; + +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; + +/** + * 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; +} + +/** + * 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 = Array.isArray; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * 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(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; +} + +/** Used for built-in method references. */ +var objectProto$1 = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString$1 = objectProto$1.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(value) { + return nativeObjectToString$1.call(value); +} + +/** `Object#toString` result references. */ +var nullTag = '[object Null]', + undefinedTag = '[object Undefined]'; + +/** Built-in value references. */ +var symToStringTag$1 = Symbol ? Symbol.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(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag$1 && symToStringTag$1 in Object(value)) + ? getRawTag(value) + : objectToString(value); +} + +/** + * 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 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return value != null && typeof value == 'object'; +} + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && baseGetTag(value) == symbolTag); +} + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + +/** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +/** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ +function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; +} + +/** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ +function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); +} + +/** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; +} + +/** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ +function baseIsNaN(value) { + return value !== value; +} + +/** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; +} + +/** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseIndexOf(array, value, fromIndex) { + return value === value + ? strictIndexOf(array, value, fromIndex) + : baseFindIndex(array, baseIsNaN, fromIndex); +} + +/** + * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the last unmatched string symbol. + */ +function charsEndIndex(strSymbols, chrSymbols) { + var index = strSymbols.length; + + while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; +} + +/** + * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the first unmatched string symbol. + */ +function charsStartIndex(strSymbols, chrSymbols) { + var index = -1, + length = strSymbols.length; + + while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; +} + +/** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function asciiToArray(string) { + return string.split(''); +} + +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f', + reComboHalfMarksRange = '\\ufe20-\\ufe2f', + rsComboSymbolsRange = '\\u20d0-\\u20ff', + rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, + rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsZWJ = '\\u200d'; + +/** 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/). */ +var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + +/** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ +function hasUnicode(string) { + return reHasUnicode.test(string); +} + +/** Used to compose unicode character classes. */ +var rsAstralRange$1 = '\\ud800-\\udfff', + rsComboMarksRange$1 = '\\u0300-\\u036f', + reComboHalfMarksRange$1 = '\\ufe20-\\ufe2f', + rsComboSymbolsRange$1 = '\\u20d0-\\u20ff', + rsComboRange$1 = rsComboMarksRange$1 + reComboHalfMarksRange$1 + rsComboSymbolsRange$1, + rsVarRange$1 = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsAstral = '[' + rsAstralRange$1 + ']', + rsCombo = '[' + rsComboRange$1 + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange$1 + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsZWJ$1 = '\\u200d'; + +/** Used to compose unicode regexes. */ +var reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange$1 + ']?', + rsOptJoin = '(?:' + rsZWJ$1 + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + +/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ +var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + +/** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function unicodeToArray(string) { + return string.match(reUnicode) || []; +} + +/** + * Converts `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function stringToArray(string) { + return hasUnicode(string) + ? unicodeToArray(string) + : asciiToArray(string); +} + +/** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ +function toString(value) { + return value == null ? '' : baseToString(value); +} + +/** Used to match leading and trailing whitespace. */ +var reTrim = /^\s+|\s+$/g; + +/** + * Removes leading and trailing whitespace or specified characters from `string`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {string} Returns the trimmed string. + * @example + * + * _.trim(' abc '); + * // => 'abc' + * + * _.trim('-_-abc-_-', '_-'); + * // => 'abc' + * + * _.map([' foo ', ' bar '], _.trim); + * // => ['foo', 'bar'] + */ +function trim(string, chars, guard) { + string = toString(string); + if (string && (guard || chars === undefined)) { + return string.replace(reTrim, ''); + } + if (!string || !(chars = baseToString(chars))) { + return string; + } + var strSymbols = stringToArray(string), + chrSymbols = stringToArray(chars), + start = charsStartIndex(strSymbols, chrSymbols), + end = charsEndIndex(strSymbols, chrSymbols) + 1; + + return castSlice(strSymbols, start, end).join(''); +} + +/** + * Check several parameter that there is something in the param + * @param {*} param input + * @return {boolean} + */ + var isNotEmpty = function (a) { + if (isArray(a)) { + return true; + } + return a !== undefined && a !== null && trim(a) !== ''; +}; + +/** `Object#toString` result references. */ +var numberTag = '[object Number]'; + +/** + * 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 + * + * _.isNumber('3'); + * // => false + */ +function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && baseGetTag(value) == numberTag); +} + +/** + * 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 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ +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; +} + +/** `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 + * + * _.isString(1); + * // => false + */ +function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); +} + +// 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) ) +}; + +// validate string type +/** + * @param {string} value expected value + * @return {boolean} true if OK + */ +var checkIsString = function(value) { + return (trim(value) !== '') ? isString(value) : false; +}; + +// check for boolean + +/** + * @param {boolean} value expected + * @return {boolean} true if OK + */ +var checkIsBoolean = function(value) { + return value !== null && value !== undefined && typeof value === 'boolean' +}; + +// validate any thing only check if there is something + +/** + * @param {*} value the value + * @param {boolean} [checkNull=true] strict check if there is null value + * @return {boolean} true is OK + */ +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; +}; + +// 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!'; +// @TODO the jsdoc return array. and we should also allow array syntax +var DEFAULT_TYPE$1 = DEFAULT_TYPE; +var ARRAY_TYPE_LFT$1 = ARRAY_TYPE_LFT; +var ARRAY_TYPE_RGT$1 = ARRAY_TYPE_RGT; + +var TYPE_KEY$1 = TYPE_KEY; +var OPTIONAL_KEY$1 = OPTIONAL_KEY; +var ENUM_KEY$1 = ENUM_KEY; +var ARGS_KEY$1 = ARGS_KEY; +var CHECKER_KEY$1 = CHECKER_KEY; +var ALIAS_KEY$1 = ALIAS_KEY; + +var ARRAY_TYPE$1 = ARRAY_TYPE; +var OBJECT_TYPE$1 = OBJECT_TYPE; +var STRING_TYPE$1 = STRING_TYPE; +var BOOLEAN_TYPE$1 = BOOLEAN_TYPE; +var NUMBER_TYPE$1 = NUMBER_TYPE; +var KEY_WORD$1 = KEY_WORD; +var OR_SEPERATOR$1 = OR_SEPERATOR; + +// not actually in use +// export const NUMBER_TYPES = JSONQL_CONSTANTS.NUMBER_TYPES; + +// primitive types + +/** + * 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 + */ +var combineFn = function(type) { + switch (type) { + case NUMBER_TYPE$1: + return checkIsNumber; + case STRING_TYPE$1: + return checkIsString; + case BOOLEAN_TYPE$1: + return checkIsBoolean; + default: + return checkIsAny; + } +}; + +// validate array type + +/** + * @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 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 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) > -1 && type.indexOf(ARRAY_TYPE_RGT$1) > -1) { + var _type = type.replace(ARRAY_TYPE_LFT$1, '').replace(ARRAY_TYPE_RGT$1, ''); + if (_type.indexOf(OR_SEPERATOR$1)) { + return _type.split(OR_SEPERATOR$1) + } + return [_type] + } + return false; +}; + +/** + * 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 + */ +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; +}; + +/** + * 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); + +/** `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 `_.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 = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; +} + +/** + * 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(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 = createBaseFor(); + +/** + * 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(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} + +/** `Object#toString` result references. */ +var argsTag = '[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(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; +} + +/** Used for built-in method references. */ +var objectProto$3 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$2 = objectProto$3.hasOwnProperty; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto$3.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$2.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); +}; + +/** + * 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; +} + +/** Detect free variable `exports`. */ +var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + +/** 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; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeIsBuffer = Buffer ? Buffer.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 = nativeIsBuffer || stubFalse; + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** Used to detect unsigned integer values. */ +var reIsUint = /^(?: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(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); +} + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER$1 = 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(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER$1; +} + +/** `Object#toString` result references. */ +var argsTag$1 = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[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] = +typedArrayTags[mapTag] = typedArrayTags[numberTag$1] = +typedArrayTags[objectTag$1] = typedArrayTags[regexpTag] = +typedArrayTags[setTag] = typedArrayTags[stringTag$1] = +typedArrayTags[weakMapTag] = 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(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(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(func) { + return function(value) { + return func(value); + }; +} + +/** 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; + +/** Detect free variable `process` from Node.js. */ +var freeProcess = moduleExports$1 && freeGlobal.process; + +/** Used to access faster Node.js helpers. */ +var nodeUtil = (function() { + try { + // Use `util.types` for Node.js 10+. + var types = freeModule$1 && freeModule$1.require && freeModule$1.require('util').types; + + 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; + +/** + * 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 = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + +/** Used for built-in method references. */ +var objectProto$4 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$3 = objectProto$4.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(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$3.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; +} + +/** Used for built-in method references. */ +var objectProto$5 = 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$5; + + return value === proto; +} + +/* 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$6 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$4 = objectProto$6.hasOwnProperty; + +/** + * 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 baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty$4.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; +} + +/** + * 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(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); +} + +/** `Object#toString` result references. */ +var asyncTag = '[object AsyncFunction]', + funcTag$1 = '[object Function]', + genTag = '[object GeneratorFunction]', + proxyTag = '[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(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$1 || tag == genTag || tag == asyncTag || tag == proxyTag; +} + +/** + * 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$1(value) { + return value != null && isLength(value.length) && !isFunction(value); +} + +/** + * 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); +} + +/** + * 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); +} + +/** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ +function listCacheClear() { + this.__data__ = []; + this.size = 0; +} + +/** + * 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(value, other) { + return value === other || (value !== value && other !== other); +} + +/** + * 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(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; +} + +/** 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. + * + * @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(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; +} + +/** + * 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. + */ +function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(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(key) { + return assocIndexOf(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(key, value) { + var data = this.__data__, + index = assocIndexOf(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(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.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. + * + * @private + * @name clear + * @memberOf Stack + */ +function stackClear() { + this.__data__ = new ListCache; + 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(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(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(key) { + return this.__data__.has(key); +} + +/** Used to detect overreaching core-js shims. */ +var coreJsData = root['__core-js_shared__']; + +/** 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) : ''; +}()); + +/** + * 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(func) { + return !!maskSrcKey && (maskSrcKey in func); +} + +/** Used for built-in method references. */ +var funcProto$1 = Function.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString$1 = funcProto$1.toString; + +/** + * 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 ''; +} + +/** + * 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$7 = 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$5 = objectProto$7.hasOwnProperty; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + funcToString$2.call(hasOwnProperty$5).replace(reRegExpChar, '\\$&') + .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(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(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(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(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'); + +/* Built-in method references that are verified to be native. */ +var nativeCreate = getNative(Object, 'create'); + +/** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ +function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(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(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 = '__lodash_hash_undefined__'; + +/** Used for built-in method references. */ +var objectProto$8 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$6 = objectProto$8.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(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty$6.call(data, key) ? data[key] : undefined; +} + +/** Used for built-in method references. */ +var objectProto$9 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$7 = objectProto$9.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(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty$7.call(data, key); +} + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED$1 = '__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(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. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +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]); + } +} + +// 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. + * + * @private + * @name clear + * @memberOf MapCache + */ +function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map$1 || ListCache), + 'string': new Hash + }; +} + +/** + * 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(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(map, key) { + var data = map.__data__; + return isKeyable(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(key) { + var result = getMapData(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(key) { + return getMapData(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(key) { + return getMapData(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(key, value) { + var data = getMapData(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(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.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 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. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +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; + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED$2 = '__lodash_hash_undefined__'; + +/** + * 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; +} + +/** + * 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); +} + +/** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ +function SetCache(values) { + var index = -1, + length = values == null ? 0 : values.length; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } +} + +// Add methods to `SetCache`. +SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; +SetCache.prototype.has = setCacheHas; + +/** + * 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; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; +} + +/** + * 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`. + */ +function cacheHas(cache, key) { + return cache.has(key); +} + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** + * 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; + + 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; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + 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; +} + +/** Built-in value references. */ +var Uint8Array = root.Uint8Array; + +/** + * 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); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; +} + +/** + * 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); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; +} + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG$1 = 1, + COMPARE_UNORDERED_FLAG$1 = 2; + +/** `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]'; + +var arrayBufferTag$1 = '[object ArrayBuffer]', + dataViewTag$1 = '[object DataView]'; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto$1 = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto$1 ? symbolProto$1.valueOf : undefined; + +/** + * 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; + + case arrayBufferTag$1: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + + 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); + + case errorTag$1: + return object.name == other.name && object.message == other.message; + + 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 + ''); + + case mapTag$1: + var convert = mapToArray; + + case setTag$1: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG$1; + convert || (convert = setToArray); + + 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; + + // 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; + + case symbolTag$1: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + 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; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; +} + +/** + * 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)); +} + +/** + * 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 []; +} + +/** Used for built-in method references. */ +var objectProto$a = Object.prototype; + +/** Built-in value references. */ +var propertyIsEnumerable$1 = objectProto$a.propertyIsEnumerable; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetSymbols = Object.getOwnPropertySymbols; + +/** + * 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); + }); +}; + +/** + * 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); +} + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG$2 = 1; + +/** Used for built-in method references. */ +var objectProto$b = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$8 = objectProto$b.hasOwnProperty; + +/** + * 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; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty$8.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); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + 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; + + // 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; +} + +/* Built-in method references that are verified to be native. */ +var DataView = getNative(root, 'DataView'); + +/* Built-in method references that are verified to be native. */ +var Promise$1 = getNative(root, 'Promise'); + +/* Built-in method references that are verified to be native. */ +var Set$1 = getNative(root, 'Set'); + +/* Built-in method references that are verified to be native. */ +var WeakMap$1 = getNative(root, 'WeakMap'); + +/** `Object#toString` result references. */ +var mapTag$2 = '[object Map]', + objectTag$2 = '[object Object]', + promiseTag = '[object Promise]', + setTag$2 = '[object Set]', + weakMapTag$1 = '[object WeakMap]'; + +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); + +/** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +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; + }; +} + +var getTag$1 = getTag; + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG$3 = 1; + +/** `Object#toString` result references. */ +var argsTag$2 = '[object Arguments]', + arrayTag$1 = '[object Array]', + objectTag$3 = '[object Object]'; + +/** Used for built-in method references. */ +var objectProto$c = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$9 = objectProto$c.hasOwnProperty; + +/** + * 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`. + */ +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); + + 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; + } + 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$9.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty$9.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + 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); +} + +/** + * 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); +} + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG$4 = 1, + COMPARE_UNORDERED_FLAG$2 = 2; + +/** + * 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; + + 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]; + + 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; +} + +/** + * 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); +} + +/** + * 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; + + while (length--) { + var key = result[length], + value = object[key]; + + result[length] = [key, value, isStrictComparable(value)]; + } + return result; +} + +/** + * 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. + */ +function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + return false; + } + return object[key] === srcValue && + (srcValue !== undefined || (key in Object(object))); + }; +} + +/** + * 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. + */ +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); + }; +} + +/** Used to match property names within property paths. */ +var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/; + +/** + * 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`. + */ +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'; + +/** + * 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; + */ +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; +} + +// Expose `MapCache`. +memoize.Cache = MapCache; + +/** Used as the maximum memoize cache size. */ +var MAX_MEMOIZE_SIZE = 500; + +/** + * 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(); + } + return key; + }); + + var cache = result.cache; + return result; +} + +/** Used to match property names within property paths. */ +var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + +/** Used to match backslashes in property paths. */ +var reEscapeChar = /\\(\\)?/g; + +/** + * 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; +}); + +/** + * 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)); +} + +/** Used as references for various `Number` constants. */ +var INFINITY$1 = 1 / 0; + +/** + * 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; +} + +/** + * 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); + }; +} + +/** + * 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(value) { + return value; +} + +/** + * 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); +} + +// 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; + + 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; +}; + +/** + * fold this into it's own function to handler different object type + * @param {object} p the prepared object for process + * @return {boolean} + */ +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) +}; + +// 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 + +/** + * 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 + */ +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; +}; + +/** + * actually picking the validator + * @param {*} type for checking + * @param {*} value for checking + * @return {boolean} true on OK + */ +var validateHandler = function(type, value) { + var tmp; + switch (true) { + case type === OBJECT_TYPE$1: + // debugFn('call OBJECT_TYPE') + return !objectTypeHandler(value) + case type === ARRAY_TYPE$1: + // 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) + } +}; + +/** + * 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 + */ +var getOptionalValue = function(arg, param) { + if (arg !== undefined) { + return arg; + } + return (param.optional === true && param.defaultvalue !== undefined ? param.defaultvalue : null) +}; + +/** + * 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 + */ +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 JsonqlError(PARAMS_NOT_ARRAY_ERR) + } + if (params.length === 0) { + return []; + } + if (!checkIsArray(args)) { + throw new JsonqlError(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$1 ]; + // 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(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([]) + }) +}; + +var defineProperty = (function() { + try { + var func = getNative(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(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(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(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, 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; + +/** Built-in value references. */ +var Buffer$1 = moduleExports$2 ? root.Buffer : undefined, + allocUnsafe = Buffer$1 ? Buffer$1.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(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; +} + +/** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ +function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(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(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]; + } + return array; +} + +/** 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; + }; +}()); + +/** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ +function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; +} + +/** + * 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(value) { + return isObjectLike(value) && isArrayLike$1(value); +} + +/** + * 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(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$d = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$a = objectProto$d.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(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty$a.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(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(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(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; +} + +/** + * 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(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$e = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$b = objectProto$e.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(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty$b.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(object) { + return isArrayLike$1(object) ? arrayLikeKeys(object, true) : baseKeysIn(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(value) { + return copyObject(value, keysIn(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(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); +} + +/** + * 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; + + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); +} + +/** + * 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]); + } + return func.apply(thisArg, args); +} + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = 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(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); + + 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); + }; +} + +/** + * 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; + }; +} + +/** + * 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; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeNow = Date.now; + +/** + * 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. + */ +function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; +} + +/** + * 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); + +/** + * 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 + ''); +} + +/** + * 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; +} + +/** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ +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; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + 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; + }); +} + +/** + * 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); +}); + +/** + * 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 = 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$1]; } ); + 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(_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 + } +} + +/** + * 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$1] === true && isEmpty(config[key])) + ? merge({}, value, ( obj = {}, obj[KEY_WORD$1] = true, obj )) + : ( obj$1 = {}, obj$1[ARGS_KEY$1] = config[key], obj$1[TYPE_KEY$1] = value[TYPE_KEY$1], obj$1[OPTIONAL_KEY$1] = value[OPTIONAL_KEY$1] || false, obj$1[ENUM_KEY$1] = value[ENUM_KEY$1] || false, obj$1[CHECKER_KEY$1] = value[CHECKER_KEY$1] || 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 = 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 = 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$1] ], + [( obj = {}, obj[TYPE_KEY$1] = toArray(value[TYPE_KEY$1]), obj[OPTIONAL_KEY$1] = value[OPTIONAL_KEY$1], 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; +}; + +/** + * 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$1]) { + return value[ARGS_KEY$1] + } + var check = validateHandler$1(value, cb); + if (check.length) { + // log('runValidationAction', key, value) + throw new JsonqlTypeError(key, check) + } + if (value[ENUM_KEY$1] !== false && !enumHandler(value[ARGS_KEY$1], value[ENUM_KEY$1])) { + // log(ENUM_KEY, value[ENUM_KEY]) + throw new JsonqlEnumError(key) + } + if (value[CHECKER_KEY$1] !== false && !checkerHandler(value[ARGS_KEY$1], value[CHECKER_KEY$1])) { + // log(CHECKER_KEY, value[CHECKER_KEY]) + throw new JsonqlCheckerError(key) + } + return value[ARGS_KEY$1] + } +} + +/** + * @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 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) { + /** + * 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= {}; + + 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); + +// bunch of generic helpers + +/** + * 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; }; + +// quick and dirty to turn non array to array +var toArray$1 = function (arg) { return isArray(arg) ? arg : [arg]; }; + +/** + * @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; + /* + console.info('obj', obj) + console.error(e) + throw new Error(e) + */ + } +}; + +/** + * 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('_'); +}; + +/** + * 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))); +}; + +/** + * 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$1(value)) + ); }, Reflect.apply(mainFn, null, args)) + ); + } +); +}; + +// break it out on its own because + + +/** + * This one return a different result from the chainPromises + * it will be the same like chainFns that take one promise resolve as the next fn parameter + * @param {function} initPromise a function that accept param and resolve result + * @param {array} promises array of function pass that resolve promises + * @return {promise} resolve the processed result + */ +function chainProcessPromises(initPromise) { + var promises = [], len = arguments.length - 1; + while ( len-- > 0 ) promises[ len ] = arguments[ len + 1 ]; + + return function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return ( + promises.reduce(function (promiseChain, currentTask) { return ( + promiseChain.then(function (chainResult) { return ( + currentTask(chainResult) + ); } + ) + ); }, Reflect.apply(initPromise, null, args)) + ); + } +} + +/** + * 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; + + if (Object.getOwnPropertyDescriptor(obj, name) === undefined) { + Object.defineProperty(obj, name, { + set: setter, + get: getter === null ? function() { return null; } : getter + }); + } + return obj +} + +/** + * 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; +} + +/** + * 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; + + var check = objHasProp(resolver, name); + if (overwrite === false && check !== undefined) { + // console.info(`NOT INJECTED`) + return resolver; + } + /* this will throw error! + 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 + }); + + return resolver; +} + +// 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) + ) +} + +/** + * 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; +} + +/** + * 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')) { + return contract.socket; + } + return false; +} + +/** + * @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 + * @param {boolean} [fallback=false] this is a fall back option for old code + * @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, fallback) { + if ( fallback === void 0 ) fallback = false; + + var socket = extractSocketPart(contract); + if (socket === false) { + if (fallback) { + return contract; // just return the whole contract + } + throw new JsonqlError("socket not found in contract!") + } + var nspSet = {}; + var size = 0; + var publicNamespace; + for (var resolverName in socket) { + var params = socket[resolverName]; + var namespace = params.namespace; + if (namespace) { + if (!nspSet[namespace]) { + ++size; + nspSet[namespace] = {}; + } + nspSet[namespace][resolverName] = params; + if (!publicNamespace) { + if (params.public) { + publicNamespace = namespace; + } + } + } + } + return { size: size, nspSet: nspSet, publicNamespace: publicNamespace } +} + +/** + * @NOTE ported from jsonql-ws-client + * Got to make sure the connection order otherwise + * it will hang + * @param {object} nspSet contract + * @param {string} publicNamespace like the name said + * @return {array} namespaces in order + */ +function getNamespaceInOrder(nspSet, publicNamespace) { + var names = []; // need to make sure the order! + for (var namespace in nspSet) { + if (namespace === publicNamespace) { + names[1] = namespace; + } else { + names[0] = namespace; + } + } + return names; +} + +/** + * @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 ) +); +}; + +/** + * Get name from the payload (ported back from jsonql-koa) + * @param {*} payload to extract from + * @return {string} name + */ +function getNameFromPayload(payload) { + return Object.keys(payload)[0] +} + +/** + * 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)) +} + +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) +} +// wrapper to make sure it string +function hashCode2Str(s) { + return hashCode(s) + '' +} + +// making all the functionality on it's own +// import { WatchClass } from './watch' + +var SuspendClass = function SuspendClass() { + // suspend, release and queue + this.__suspend__ = null; + this.queueStore = new Set(); + /* + this.watch('suspend', function(value, prop, oldValue) { + this.logger(`${prop} set from ${oldValue} to ${value}`) + // it means it set the suspend = true then release it + if (oldValue === true && value === false) { + // we want this happen after the return happens + setTimeout(() => { + this.release() + }, 1) + } + return value; // we need to return the value to store it + }) + */ +}; + +var prototypeAccessors = { $suspend: { configurable: true },$queues: { configurable: true } }; + +/** + * setter to set the suspend and check if it's boolean value + * @param {boolean} value to trigger + */ +prototypeAccessors.$suspend.set = function (value) { + var this$1 = this; + + if (typeof value === 'boolean') { + var lastValue = this.__suspend__; + this.__suspend__ = value; + this.logger('($suspend)', ("Change from " + lastValue + " --> " + value)); + if (lastValue === true && value === false) { + setTimeout(function () { + this$1.release(); + }, 1); + } + } else { + throw new Error("$suspend only accept Boolean value!") + } +}; + +/** + * queuing call up when it's in suspend mode + * @param {any} value + * @return {Boolean} true when added or false when it's not + */ +SuspendClass.prototype.$queue = function $queue () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (this.__suspend__ === true) { + this.logger('($queue)', 'added to $queue', args); + // there shouldn't be any duplicate ... + this.queueStore.add(args); + } + return this.__suspend__; +}; + +/** + * 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 [] +}; + +/** + * Release the queue + * @return {int} size if any + */ +SuspendClass.prototype.release = function release () { + var this$1 = this; + + var size = this.queueStore.size; + this.logger('(release)', ("Release was called " + size)); + if (size > 0) { + var queue = Array.from(this.queueStore); + this.queueStore.clear(); + this.logger('queue', queue); + queue.forEach(function (args) { + this$1.logger(args); + Reflect.apply(this$1.$trigger, this$1, args); + }); + this.logger(("Release size " + (this.queueStore.size))); + } +}; + +Object.defineProperties( SuspendClass.prototype, prototypeAccessors ); + +// break up the main file because its getting way too long + +var NbEventServiceBase = /*@__PURE__*/(function (SuspendClass) { + function NbEventServiceBase(config) { + if ( config === void 0 ) 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 ( SuspendClass ) NbEventServiceBase.__proto__ = SuspendClass; + NbEventServiceBase.prototype = Object.create( SuspendClass && SuspendClass.prototype ); + NbEventServiceBase.prototype.constructor = NbEventServiceBase; + + var prototypeAccessors = { is: { configurable: true },normalStore: { configurable: true },lazyStore: { configurable: true } }; + + // for id if the instance is this class + prototypeAccessors.is.get = function () { + return 'nb-event-service' + }; + + /** + * validate the event name(s) + * @param {string[]} evt event name + * @return {boolean} true when OK + */ + NbEventServiceBase.prototype.validateEvt = function validateEvt () { + var this$1 = this; + var evt = [], len = arguments.length; + while ( len-- ) evt[ len ] = arguments[ len ]; + + evt.forEach(function (e) { + if (typeof e !== 'string') { + this$1.logger('(validateEvt)', e); + throw new Error("event name must be string type!") + } + }); + return true; + }; + + /** + * Simple quick check on the two main parameters + * @param {string} evt event name + * @param {function} callback function to call + * @return {boolean} true when OK + */ + NbEventServiceBase.prototype.validate = function validate (evt, callback) { + if (this.validateEvt(evt)) { + if (typeof callback === 'function') { + return true; + } + } + throw new Error("callback required to be function type!") + }; + + /** + * Check if this type is correct or not added in V1.5.0 + * @param {string} type for checking + * @return {boolean} true on OK + */ + NbEventServiceBase.prototype.validateType = function validateType (type) { + var types = ['on', 'only', 'once', 'onlyOnce']; + return !!types.filter(function (t) { return type === t; }).length; + }; + + /** + * Run the callback + * @param {function} callback function to execute + * @param {array} payload for callback + * @param {object} ctx context or null + * @return {void} the result store in $done + */ + NbEventServiceBase.prototype.run = function run (callback, payload, ctx) { + this.logger('(run)', callback, payload, ctx); + this.$done = Reflect.apply(callback, ctx, this.toArray(payload)); + }; + + /** + * Take the content out and remove it from store id by the name + * @param {string} evt event name + * @param {string} [storeName = lazyStore] name of store + * @return {object|boolean} content or false on not found + */ + NbEventServiceBase.prototype.takeFromStore = function takeFromStore (evt, storeName) { + if ( storeName === void 0 ) storeName = 'lazyStore'; + + var store = this[storeName]; // it could be empty at this point + if (store) { + this.logger('(takeFromStore)', storeName, store); + if (store.has(evt)) { + var content = store.get(evt); + this.logger('(takeFromStore)', ("has " + evt), content); + store.delete(evt); + return content; + } + return false; + } + throw new Error((storeName + " is not supported!")) + }; + + /** + * The add to store step is similar so make it generic for resuse + * @param {object} store which store to use + * @param {string} evt event name + * @param {spread} args because the lazy store and normal store store different things + * @return {array} store and the size of the store + */ + NbEventServiceBase.prototype.addToStore = function addToStore (store, evt) { + var args = [], len = arguments.length - 2; + while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; + + var fnSet; + if (store.has(evt)) { + this.logger('(addToStore)', (evt + " existed")); + fnSet = store.get(evt); + } else { + this.logger('(addToStore)', ("create new Set for " + evt)); + // this is new + fnSet = new Set(); + } + // lazy only store 2 items - this is not the case in V1.6.0 anymore + // we need to check the first parameter is string or not + if (args.length > 2) { + if (Array.isArray(args[0])) { // lazy store + // check if this type of this event already register in the lazy store + var t = args[2]; + if (!this.checkTypeInLazyStore(evt, t)) { + fnSet.add(args); + } + } 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] + }; + + /** + * @param {array} args for compare + * @param {object} fnSet A Set to search from + * @return {boolean} true on exist + */ + NbEventServiceBase.prototype.checkContentExist = function checkContentExist (args, fnSet) { + var list = Array.from(fnSet); + return !!list.filter(function (l) { + var hash = l[0]; + if (hash === args[0]) { + return true; + } + return false; + }).length; + }; + + /** + * get the existing type to make sure no mix type add to the same store + * @param {string} evtName event name + * @param {string} type the type to check + * @return {boolean} true you can add, false then you can't add this type + */ + NbEventServiceBase.prototype.checkTypeInStore = function checkTypeInStore (evtName, type) { + this.validateEvt(evtName, type); + var all = this.$get(evtName, true); + if (all === false) { + // pristine it means you can add + return true; + } + // it should only have ONE type in ONE event store + return !all.filter(function (list) { + var t = list[3]; + return type !== t; + }).length; + }; + + /** + * This is checking just the lazy store because the structure is different + * therefore we need to use a new method to check it + */ + NbEventServiceBase.prototype.checkTypeInLazyStore = function checkTypeInLazyStore (evtName, type) { + this.validateEvt(evtName, type); + var store = this.lazyStore.get(evtName); + this.logger('(checkTypeInLazyStore)', store); + if (store) { + return !!Array + .from(store) + .filter(function (l) { + var t = l[2]; + return t !== type; + }).length + } + return false; + }; + + /** + * wrapper to re-use the addToStore, + * V1.3.0 add extra check to see if this type can add to this evt + * @param {string} evt event name + * @param {string} type on or once + * @param {function} callback function + * @param {object} context the context the function execute in or null + * @return {number} size of the store + */ + NbEventServiceBase.prototype.addToNormalStore = function addToNormalStore (evt, type, callback, context) { + if ( context === void 0 ) context = null; + + this.logger('(addToNormalStore)', evt, type, 'try to add to normal store'); + // @TODO we need to check the existing store for the type first! + if (this.checkTypeInStore(evt, type)) { + this.logger('(addToNormalStore)', (type + " can add to " + evt + " normal store")); + var key = this.hashFnToKey(callback); + var args = [this.normalStore, evt, key, callback, context, type]; + var ref = Reflect.apply(this.addToStore, this, args); + var _store = ref[0]; + var size = ref[1]; + this.normalStore = _store; + return size; + } + return false; + }; + + /** + * Add to lazy store this get calls when the callback is not register yet + * so we only get a payload object or even nothing + * @param {string} evt event name + * @param {array} payload of arguments or empty if there is none + * @param {object} [context=null] the context the callback execute in + * @param {string} [type=false] register a type so no other type can add to this evt + * @return {number} size of the store + */ + NbEventServiceBase.prototype.addToLazyStore = function addToLazyStore (evt, payload, context, type) { + if ( payload === void 0 ) payload = []; + if ( context === void 0 ) context = null; + if ( type === void 0 ) type = false; + + // this is add in V1.6.0 + // when there is type then we will need to check if this already added in lazy store + // and no other type can add to this lazy store + var args = [this.lazyStore, evt, this.toArray(payload), context]; + if (type) { + args.push(type); + } + var ref = Reflect.apply(this.addToStore, this, args); + var _store = ref[0]; + var size = ref[1]; + this.lazyStore = _store; + return size; + }; + + /** + * make sure we store the argument correctly + * @param {*} arg could be array + * @return {array} make sured + */ + NbEventServiceBase.prototype.toArray = function toArray (arg) { + return Array.isArray(arg) ? arg : [arg]; + }; + + /** + * setter to store the Set in private + * @param {object} obj a Set + */ + prototypeAccessors.normalStore.set = function (obj) { + NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj); + }; + + /** + * @return {object} Set object + */ + prototypeAccessors.normalStore.get = function () { + return NB_EVENT_SERVICE_PRIVATE_STORE.get(this) + }; + + /** + * setter to store the Set in lazy store + * @param {object} obj a Set + */ + prototypeAccessors.lazyStore.set = function (obj) { + NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj); + }; + + /** + * @return {object} the lazy store Set + */ + prototypeAccessors.lazyStore.get = function () { + return NB_EVENT_SERVICE_PRIVATE_LAZY.get(this) + }; + + /** + * generate a hashKey to identify the function call + * The build-in store some how could store the same values! + * @param {function} fn the converted to string function + * @return {string} hashKey + */ + NbEventServiceBase.prototype.hashFnToKey = function hashFnToKey (fn) { + return hashCode2Str(fn.toString()) + }; + + Object.defineProperties( NbEventServiceBase.prototype, prototypeAccessors ); + + return NbEventServiceBase; +}(SuspendClass)); + +// The top level +// export +var EventService = /*@__PURE__*/(function (NbStoreService) { + function EventService(config) { + if ( config === void 0 ) config = {}; + + NbStoreService.call(this, config); + } + + if ( NbStoreService ) EventService.__proto__ = NbStoreService; + EventService.prototype = Object.create( NbStoreService && NbStoreService.prototype ); + EventService.prototype.constructor = EventService; + + var prototypeAccessors = { $done: { configurable: true } }; + + /** + * logger function for overwrite + */ + EventService.prototype.logger = function logger () {}; + + ////////////////////////// + // PUBLIC METHODS // + ////////////////////////// + + /** + * Register your evt handler, note we don't check the type here, + * we expect you to be sensible and know what you are doing. + * @param {string} evt name of event + * @param {function} callback bind method --> if it's array or not + * @param {object} [context=null] to execute this call in + * @return {number} the size of the store + */ + EventService.prototype.$on = function $on (evt , callback , context) { + var this$1 = this; + if ( context === void 0 ) context = null; + + var type = 'on'; + this.validate(evt, callback); + // first need to check if this evt is in lazy store + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register first then call later + if (lazyStoreContent === false) { + this.logger('($on)', (evt + " callback is not in lazy store")); + // @TODO we need to check if there was other listener to this + // event and are they the same type then we could solve that + // register the different type to the same event name + + return this.addToNormalStore(evt, type, callback, context) + } + this.logger('($on)', (evt + " found in lazy store")); + // this is when they call $trigger before register this callback + var size = 0; + lazyStoreContent.forEach(function (content) { + var payload = content[0]; + var ctx = content[1]; + var t = content[2]; + if (t && t !== type) { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this$1.logger("($on)", ("call run on " + evt)); + this$1.run(callback, payload, context || ctx); + size += this$1.addToNormalStore(evt, type, callback, context || ctx); + }); + return size; + }; + + /** + * once only registered it once, there is no overwrite option here + * @NOTE change in v1.3.0 $once can add multiple listeners + * but once the event fired, it will remove this event (see $only) + * @param {string} evt name + * @param {function} callback to execute + * @param {object} [context=null] the handler execute in + * @return {boolean} result + */ + EventService.prototype.$once = function $once (evt , callback , context) { + if ( context === void 0 ) context = null; + + this.validate(evt, callback); + var type = 'once'; + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register before call $trigger + var nStore = this.normalStore; + if (lazyStoreContent === false) { + this.logger('($once)', (evt + " not in the lazy store")); + // v1.3.0 $once now allow to add multiple listeners + return this.addToNormalStore(evt, type, callback, context) + } else { + // now this is the tricky bit + // there is a potential bug here that cause by the developer + // if they call $trigger first, the lazy won't know it's a once call + // so if in the middle they register any call with the same evt name + // then this $once call will be fucked - add this to the documentation + this.logger('($once)', lazyStoreContent); + var list = Array.from(lazyStoreContent); + // should never have more than 1 + var ref = list[0]; + var payload = ref[0]; + var ctx = ref[1]; + var t = ref[2]; + if (t && t !== type) { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this.logger('($once)', ("call run for " + evt)); + this.run(callback, payload, context || ctx); + // remove this evt from store + this.$off(evt); + } + }; + + /** + * This one event can only bind one callbackback + * @param {string} evt event name + * @param {function} callback event handler + * @param {object} [context=null] the context the event handler execute in + * @return {boolean} true bind for first time, false already existed + */ + EventService.prototype.$only = function $only (evt, callback, context) { + var this$1 = this; + if ( context === void 0 ) context = null; + + this.validate(evt, callback); + var type = 'only'; + var added = false; + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register before call $trigger + var nStore = this.normalStore; + if (!nStore.has(evt)) { + this.logger("($only)", (evt + " add to store")); + added = this.addToNormalStore(evt, type, callback, context); + } + if (lazyStoreContent !== false) { + // there are data store in lazy store + this.logger('($only)', (evt + " found data in lazy store to execute")); + var list = Array.from(lazyStoreContent); + // $only allow to trigger this multiple time on the single handler + list.forEach( function (l) { + var payload = l[0]; + var ctx = l[1]; + var t = l[2]; + if (t && t !== type) { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this$1.logger("($only)", ("call run for " + evt)); + this$1.run(callback, payload, context || ctx); + }); + } + return added; + }; + + /** + * $only + $once this is because I found a very subtile bug when we pass a + * resolver, rejecter - and it never fire because that's OLD 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; + + this.validate(evt, callback); + var type = 'onlyOnce'; + var added = false; + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register before call $trigger + var nStore = this.normalStore; + if (!nStore.has(evt)) { + this.logger("($onlyOnce)", (evt + " add to store")); + added = this.addToNormalStore(evt, type, callback, context); + } + if (lazyStoreContent !== false) { + // there are data store in lazy store + this.logger('($onlyOnce)', lazyStoreContent); + var list = Array.from(lazyStoreContent); + // should never have more than 1 + var ref = list[0]; + var payload = ref[0]; + var ctx = ref[1]; + var t = ref[2]; + if (t && t !== 'onlyOnce') { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this.logger("($onlyOnce)", ("call run for " + evt)); + this.run(callback, payload, context || ctx); + // remove this evt from store + this.$off(evt); + } + return added; + }; + + /** + * This is a shorthand of $off + $on added in V1.5.0 + * @param {string} evt event name + * @param {function} callback to exeucte + * @param {object} [context = null] or pass a string as type + * @param {string} [type=on] what type of method to replace + * @return {} + */ + EventService.prototype.$replace = function $replace (evt, callback, context, type) { + if ( context === void 0 ) context = null; + if ( type === void 0 ) type = 'on'; + + if (this.validateType(type)) { + this.$off(evt); + var method = this['$' + type]; + this.logger("($replace)", evt, callback); + return Reflect.apply(method, this, [evt, callback, context]) + } + throw new Error((type + " is not supported!")) + }; + + /** + * trigger the event + * @param {string} evt name NOT allow array anymore! + * @param {mixed} [payload = []] pass to fn + * @param {object|string} [context = null] overwrite what stored + * @param {string} [type=false] if pass this then we need to add type to store too + * @return {number} if it has been execute how many times + */ + EventService.prototype.$trigger = function $trigger (evt , payload , context, type) { + if ( payload === void 0 ) payload = []; + if ( context === void 0 ) context = null; + if ( type === void 0 ) type = false; + + this.validateEvt(evt); + var found = 0; + // first check the normal store + var nStore = this.normalStore; + this.logger('($trigger)', 'normalStore', nStore); + if (nStore.has(evt)) { + // @1.8.0 to add the suspend queue + var added = this.$queue(evt, payload, context, type); + this.logger('($trigger)', evt, 'found; add to queue: ', added); + if (added === true) { + this.logger('($trigger)', evt, 'not 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; + }; + + /** + * 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 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) + } + }; + + /** + * 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; + + this.validateEvt(evt); + var stores = [ this.lazyStore, this.normalStore ]; + var found = false; + stores.forEach(function (store) { + if (store.has(evt)) { + found = true; + this$1.logger('($off)', evt); + store.delete(evt); + } + }); + return found; + }; + + /** + * return all the listener from the event + * @param {string} evtName event name + * @param {boolean} [full=false] if true then return the entire content + * @return {array|boolean} listerner(s) or false when not found + */ + EventService.prototype.$get = function $get (evt, full) { + if ( full === void 0 ) full = false; + + this.validateEvt(evt); + var store = this.normalStore; + if (store.has(evt)) { + return Array + .from(store.get(evt)) + .map( function (l) { + if (full) { + return l; + } + var key = l[0]; + var callback = l[1]; + return callback; + }) + } + return false; + }; + + /** + * store the return result from the run + * @param {*} value whatever return from callback + */ + prototypeAccessors.$done.set = function (value) { + this.logger('($done)', 'value: ', value); + if (this.keep) { + this.result.push(value); + } else { + this.result = value; + } + }; + + /** + * @TODO is there any real use with the keep prop? + * getter for $done + * @return {*} whatever last store result + */ + prototypeAccessors.$done.get = function () { + if (this.keep) { + this.logger('(get $done)', this.result); + return this.result[this.result.length - 1] + } + return this.result; + }; + + Object.defineProperties( EventService.prototype, prototypeAccessors ); + + return EventService; +}(NbEventServiceBase)); + +// 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 (NBEventService) { + function JsonqlWsEvt(logger) { + if (typeof logger !== 'function') { + throw new Error("Just die here the logger is not a function!") + } + // this ee will always come with the logger + // because we should take the ee from the configuration + NBEventService.call(this, { logger: logger }); + } + + if ( NBEventService ) JsonqlWsEvt.__proto__ = NBEventService; + JsonqlWsEvt.prototype = Object.create( NBEventService && NBEventService.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)); + +// mapping the resolver to their respective nsp + +/** + * Just make sure the object contain what we are looking for + * @param {object} opts configuration from checkOptions + * @return {object} the target content + */ +var getResolverList = function (contract) { + var result = extractSocketPart(contract); + if (result !== false) { + return result + } + throw new JsonqlResolverNotFoundError(MISSING_PROP_ERR) +}; + +/** + * process the contract first + * @param {object} opts configuration + * @return {object} sorted list + */ +function processContract(opts) { + var obj, obj$1; + + var contract = opts.contract; + var enableAuth = opts.enableAuth; + if (enableAuth) { + return groupByNamespace(contract) + } + return ( obj$1 = {}, obj$1[NSP_SET] = ( obj = {}, obj[JSONQL_PATH] = getResolverList(contract), obj ), obj$1[PUBLIC_NAMESPACE] = JSONQL_PATH, obj$1 ) +} + +// group all the small functions here +// we shouldn't do this anymore +var fixWss = function (url, serverType) { + // ws only allow ws:// path + if (serverType === JS_WS_NAME) { + return url.replace('http://', 'ws://') + } + return url +}; + +/** + * get a stock host name from browser + */ +var getHostName = function () { + try { + return [window.location.protocol, window.location.host].join('//') + } catch(e) { + throw new JsonqlValidationError(e) + } +}; + +/** + * Unbind the event + * @param {object} ee EventEmitter + * @param {string} namespace + * @return {void} + */ +var clearMainEmitEvt = function (ee, namespace) { + var nsps = toArray$1(namespace); + nsps.forEach(function (n) { + ee.$off(createEvt(n, EMIT_REPLY_TYPE)); + }); +}; + +// breaking it up further to share between methods + +/** + * break out to use in different places to handle the return from server + * @param {object} data from server + * @param {function} resolver NOT from promise + * @param {function} rejecter NOT from promise + * @return {void} nothing + */ +function respondHandler(data, resolver, rejecter) { + if (isObjectHasKey$1(data, ERROR_KEY)) { + // debugFn('-- rejecter called --', data[ERROR_KEY]) + rejecter(data[ERROR_KEY]); + } else if (isObjectHasKey$1(data, DATA_KEY)) { + // debugFn('-- resolver called --', data[DATA_KEY]) + resolver(data[DATA_KEY]); + } else { + // debugFn('-- UNKNOWN_RESULT --', data) + rejecter({message: UNKNOWN_RESULT, error: data}); + } +} + +// the actual trigger call method + +/** + * just wrapper + * @param {object} ee EventEmitter + * @param {string} namespace where this belongs + * @param {string} resolverName resolver + * @param {boolean} useCallbackStyle use on or not + * @param {array} args arguments + * @return {void} nothing + */ +function actionCall(ee, namespace, resolverName, useCallbackStyle, args) { + if ( args === void 0 ) args = []; + + var eventName = createEvt(namespace, EMIT_REPLY_TYPE); + var RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME; + // debugFn(`actionCall: ${eventName} --> ${resolverName}`, args) + ee.$trigger(eventName, [resolverName, toArray$1(args)]); + // once we trigger there is nothing return from the resolve + // @TODO if we need the next then call to have the result back + // then we need to listen to the event callback here as well + return new Promise(function (resolver, rejecter) { + ee.$on( + createEvt(namespace, resolverName, RESULT_SUBFIX), + function actionCallResultHandler(result) { + // debugFn(`got the first result`, result) + respondHandler(result, resolver, rejecter); + } + ); + }) +} + +// pairing with the server vesrion SEND_MSG_PROP_NAME +// last of the chain so only return the resolver (fn) +var setupSend = function (fn, ee, namespace, resolverName, params, useCallbackStyle) { return ( + objDefineProps(fn, SEND_MSG_PROP_NAME, function sendSetter(messagePayload) { + var ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME; + // debugFn('got payload for', messagePayload) + // @NOTE change from sync interface to async @ 1.0.0 + // this way we will able to catch all the error(s) + validateAsync$1(toArray$1(messagePayload), params.params, true) + .then(function (result) { + // here is the different we don't throw error instead we trigger onError + if (result[ERROR_KEY] && result[ERROR_KEY].length) { + // debugFn(`got ERROR_KEY`, result[ERROR_KEY]) + ee.$call( + createEvt(namespace, resolverName, ERROR_SUBFIX), + [new JsonqlValidationError(resolverName, result[ERROR_KEY])] + ); + } else { + // return it just for the catch to work - if any + return actionCall(ee, namespace, resolverName, useCallbackStyle, messagePayload) + } + }) + .catch(function (err) { + // debugFn(`error after validateAsync`, err) + ee.$call( + createEvt(namespace, resolverName, ERROR_SUBFIX), + [new JsonqlValidationError(resolverName, err)] + ); + }); + }, function sendGetter() { // add in 1.1.4 + return function sendGetterAction() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return validateAsync$1(args, params.params, true) + .then(function (_args) { return actionCall(ee, namespace, resolverName, useCallbackStyle, _args); }) + .catch(finalCatch) + } + }) +); }; + +// @TODO using the obj.on syntax to do the same thing + +/** + * Add extra property to the resolver via the getter + * @param {function} fn the resolver itself + * @param {object} ee event emitter + * @param {string} namespace the namespace this belongs to + * @param {string} resolverName resolver namee + * @param {object} params from the contract + * @return {array} same as what goes in + */ +function setupCallbackApi(fn, ee, namespace, resolverName, params) { + return [ + injectToFn(fn, CB_FN_NAME, function(evtName, callback) { + if (isString$1(evtName) && isFunc(callback)) { + switch(evtName) { + case RESULT_PROP_NAME: + ee.$on( + createEvt(namespace, resolverName, ON_RESULT_PROP_NAME), + function resultHandler(result) { + respondHandler(result, callback, function (error) { + ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error); + }); + } + ); + break; + // register the handler for this message event + case MESSAGE_PROP_NAME: + ee.$only( + createEvt(namespace, resolverName, ON_MESSAGE_PROP_NAME), + function onMessageCallback(args) { + respondHandler(args, callback, function (error) { + ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error); + }); + } + ); + break; + case READY_PROP_NAME: + ee.$only( + createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), + callback + ); + break; + default: + ee.$trigger( + createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), + new JsonqlError(resolverName, ("Unknown event name " + evtName + "!")) + ); + } + } + }), + ee, + namespace, + resolverName, + params + ] +} + +// break up the original setup resolver method here + +/** + * The first one in the chain + * @return {array} + */ +var setupNamespace = function (fn, ee, namespace, resolverName, params, useCallbackStyle) { return [ + injectToFn(fn, MY_NAMESPACE, namespace), + ee, + namespace, + resolverName, + params, + useCallbackStyle +]; }; + +// onResult handler +var setupOnResult = function (fn, ee, namespace, resolverName, params, useCallbackStyle) { return [ + objDefineProps(fn, ON_RESULT_PROP_NAME, function(resultCallback) { + if (isFunc(resultCallback)) { + ee.$on( + createEvt(namespace, resolverName, ON_RESULT_PROP_NAME), + function resultHandler(result) { + respondHandler(result, resultCallback, function (error) { + ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error); + }); + } + ); + } + }), + ee, + namespace, + resolverName, + params, + useCallbackStyle +]; }; + +// we do need to add the send prop back because it's the only way to deal with +// bi-directional data stream +var setupOnMessage = function (fn, ee, namespace, resolverName, params, useCallbackStyle) { return [ + objDefineProps(fn, ON_MESSAGE_PROP_NAME, function(messageCallback) { + // we expect this to be a function + if (isFunc(messageCallback)) { + // did that add to the callback + var onMessageCallback = function (args) { + respondHandler(args, messageCallback, function (error) { + ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error); + }); + }; + // register the handler for this message event + ee.$only(createEvt(namespace, resolverName, ON_MESSAGE_PROP_NAME), onMessageCallback); + } + }), + ee, + namespace, + resolverName, + params, + useCallbackStyle +]; }; + +// add an ON_ERROR_PROP_NAME handler +var setupOnError = function (fn, ee, namespace, resolverName, params, useCallbackStyle) { return [ + objDefineProps(fn, ON_ERROR_PROP_NAME, function(resolverErrorHandler) { + if (isFunc(resolverErrorHandler)) { + // please note ON_ERROR_PROP_NAME can add multiple listners + ee.$only(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), resolverErrorHandler); + } + }), + ee, + namespace, + resolverName, + params, + useCallbackStyle +]; }; + +/** + * Add extra property to the resolver + * @param {string} namespace where this belongs + * @param {string} resolverName name as event name + * @param {object} params from contract + * @param {function} fn resolver function + * @param {object} ee EventEmitter + * @param {boolean} useCallbackStyle new callback style + * @return {function} resolver + */ +function setupResolver(namespace, resolverName, params, fn, ee, useCallbackStyle) { + // also need to setup a getter to get back the namespace of this resolver + var args = [setupNamespace]; + useCallbackStyle ? args.push(setupCallbackApi) : args.push(setupOnResult, setupOnMessage, setupOnError); + args.push(setupSend); + // get the executor + var executor = Reflect.apply(chainFns, null, args); + + return Reflect.apply(executor, null, [fn, ee, namespace, resolverName, params, useCallbackStyle]) +} + +// put all the resolver related methods here to make it more clear + +/** + * create the actual function to send message to server + * @param {object} ee EventEmitter instance + * @param {string} namespace this resolver end point + * @param {string} resolverName name of resolver as event name + * @param {object} params from contract + * @param {boolean} useCallbackStyle on style or not + * @return {function} resolver + */ +function createResolver(ee, namespace, resolverName, params, useCallbackStyle) { + // note we pass the new withResult=true option + return function() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return validateAsync$1(args, params.params, true) + .then(function (_args) { return actionCall(ee, namespace, resolverName, useCallbackStyle, _args); }) + .catch(finalCatch) + } +} + +/** + * The problem is the namespace can have more than one + * and we only have on onError message + * @param {object} obj the client itself + * @param {object} ee Event Emitter + * @param {object} nspSet namespace keys + * @param {boolean} useCallbackStyle use cb or not + * @return {object} obj with onError prop + */ +function createNamespaceErrorHandler(obj, ee, nspSet) { + // using the onError as name + // @TODO we should follow the convention earlier + // make this a setter for the obj itself + return objDefineProps(obj, ON_ERROR_PROP_NAME, function namespaceErrorCallbackHandler(namespaceErrorHandler) { + if (isFunc(namespaceErrorHandler)) { + // please note ON_ERROR_PROP_NAME can add multiple listners + for (var namespace in nspSet) { + // 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_PROP_NAME), namespaceErrorHandler); + } + } + }) +} + +/** + * This event will fire when the socket.io.on('connection') and ws.onopen + * @param {object} obj the client itself + * @param {object} ee Event Emitter + * @param {object} nspSet namespace keys + * @return {object} obj with onReady prop + */ +function createOnReadyhandler(obj, ee, nspSet) { + return objDefineProps(obj, ON_READY_PROP_NAME, function onReadyCallbackHandler(onReadyCallback) { + if (isFunc(onReadyCallback)) { + // reduce it down to just one flat level + ee.$on(ON_READY_PROP_NAME, onReadyCallback); + } + }) +} + +/** + * This event will fire when the socket.io.on('connection') and ws.onopen + * Plus this will check if it's the private namespace that fired the event + * @param {object} obj the client itself + * @param {object} ee Event Emitter + * @param {object} opts configuration + * @return {object} obj with onLogin prop + */ +function createOnLoginhandler(obj, ee, opts) { + if (opts.enableAuth) { + return objDefineProps(obj, ON_LOGIN_PROP_NAME, function onLoginCallbackHandler(onLoginCallback) { + if (isFunc(onLoginCallback)) { + // only one callback can registered with it, TBC + ee.$only(ON_LOGIN_PROP_NAME, onLoginCallback); + } + }) + } + // just skip it + return obj +} + +/** + * when useCallbackStyle=true use this instead of the above method + * @param {object} obj the base object to attach to + * @param {object} ee EventEmitter + * @param {object} nspSet the map + * @param {object} opts configuration + * @return {object} obj + */ +function createCallbackHandler(obj, ee, nspSet, opts) { + return injectToFn(obj, CB_FN_NAME, function onHandler(evtName, callback) { + if (isString$1(evtName) && isFunc(callback)) { + switch (evtName) { + case ERROR_PROP_NAME: + for (var namespace in nspSet) { + // 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, ERROR_PROP_NAME), callback); + } + break; + case LOGIN_PROP_NAME: // @TODO should only available when enableAuth=true + ee.$only(LOGIN_PROP_NAME, callback); + break; + case READY_PROP_NAME: + ee.$on(READY_PROP_NAME, callback); + break; + default: + ee.$trigger(ERROR_PROP_NAME, new JsonqlError(CB_FN_NAME, ("Unknown event name " + evtName + "!"))); + } + } + // @TODO need to issue another error here! + }) +} + +// take out from the resolver-methods + +/** + * @TODO this is now become unnecessary because the login is a slave to the + * http-client - but keep this for now and see what we want to do with it later + * break out from createAuthMethods to allow chaining call + * @param {object} obj the main client object + * @param {object} ee event emitter + * @param {object} opts configuration + * @return {array} modified input + */ +var setupLoginHandler = function (obj, ee, opts) { return [ + injectToFn(obj, opts.loginHandlerName, function loginHandler(token) { + if (token && isString$1(token)) { + return ee.$trigger(LOGIN_EVENT_NAME, [token]) + } + // should trigger a global error instead @TODO + throw new JsonqlValidationError(opts.loginHandlerName, ("Unexpected token " + token)) + }), + ee, + opts +]; }; + +/** + * break out from createAuthMethods to allow chaining call - final in chain + * @param {object} obj the main client object + * @param {object} ee event emitter + * @param {object} opts configuration + * @return {object} the modified obj + */ +var setupLogoutHandler = function (obj, ee, opts) { return ( + injectToFn(obj, opts.logoutHandlerName, function logoutHandler() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + ee.$trigger(LOGOUT_EVENT_NAME, args); + }) +); }; + +/** + * Create auth related methods + * @param {object} obj the client itself + * @param {object} ee Event Emitter + * @param {object} opts configuration + * @return {object} obj with auth methods if any + */ +function createAuthMethods(obj, ee, opts) { + if (opts.enableAuth) { + return chainFns(setupLoginHandler, setupLogoutHandler)(obj, ee, opts) + } + return obj +} + +// resolvers generator + +/** + * step one get the obj map with the namespace + * @param {object} opts configuration + * @param {object} nspMap resolvers index by their namespace + * @param {object} ee EventEmitter + * @return {promise} resolve the obj mapped, and start the chain + */ +function getMappedObj(opts, nspMap, ee) { + var obj = {}; + // let resolverNames = []; + var nspSet = nspMap.nspSet; + var useCallbackStyle = opts.useCallbackStyle; // @1.2.1 + for (var namespace in nspSet) { + var list = nspSet[namespace]; + for (var resolverName in list) { + // resolverNames.push(resolverName) + var params = list[resolverName]; + var fn = createResolver(ee, namespace, resolverName, params, useCallbackStyle); + // this should set as a getter therefore can not be overwrite by accident + // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee) + obj = injectToFn(obj, resolverName, setupResolver(namespace, resolverName, params, fn, ee, useCallbackStyle)); + } + } + // move this two method down to helpers + // we want these methods visible in debug or console.log + obj.devHelpers = { + // this is a helper method for the developer to know the namespace inside + getNsp: function () { return Object.keys(nspSet); }, + // simple get version trick + getVer: function () { return opts.version || 'NOT SET'; } + // not really necessary because the dev can query the contract + // getResolverNames: () => resolverNames + }; + // resolve the obj to start the chain + // chain the result to allow the chain processing + return Promise.resolve(obj) +} + +/** + * prepare the methods + * @param {object} opts configuration + * @param {object} nspMap resolvers index by their namespace + * @param {object} ee EventEmitter + * @return {object} of resolvers + * @public + */ +function generator(opts, nspMap, ee) { + var nspSet = nspMap.nspSet; + var useCallbackStyle = opts.useCallbackStyle; + var enableAuth = opts.enableAuth; + var args = [getMappedObj]; + if (useCallbackStyle) { + args.push(function (obj) { return createCallbackHandler(obj, ee, nspSet); }); + } else { + args.push( + function (obj1) { return createNamespaceErrorHandler(obj1, ee, nspSet); }, + function (obj2) { return createOnReadyhandler(obj2, ee); } + ); + if (enableAuth) { + args.push(function (obj3) { return createOnLoginhandler(obj3, ee, opts); }); + } + } + // this only apply to when enableAuth = true + if (enableAuth) { + args.push(function (obj4) { return createAuthMethods(obj4, ee, opts); }); + } + // run it + var executor = Reflect.apply(chainProcessPromises, null, args); + return executor(opts, nspMap, ee) +} + +var obj, obj$1; +var AVAILABLE_METHODS = [IO_ROUNDTRIP_LOGIN, IO_HANDSHAKE_LOGIN]; + +var wsCoreDefaultOptions = { + useCallbackStyle: createConfig$1(false, [BOOLEAN_TYPE]), + loginHandlerName: createConfig$1(ISSUER_NAME, [STRING_TYPE]), + logoutHandlerName: createConfig$1(LOGOUT_NAME, [STRING_TYPE]), + // this is for socket.io + loginMethod: createConfig$1(IO_HANDSHAKE_LOGIN, [STRING_TYPE], ( obj = {}, obj[ENUM_KEY] = AVAILABLE_METHODS, obj )), + // we will use this for determine the socket.io client type as well - @TODO remove or rename + useJwt: createConfig$1(true, [BOOLEAN_TYPE, STRING_TYPE]), + // this is going to replace the use of useJwt === string next + authStrKey: createConfig$1(null, [STRING_TYPE]), + hostname: createConfig$1(false, [STRING_TYPE]), + namespace: createConfig$1(JSONQL_PATH, [STRING_TYPE]), + wsOptions: createConfig$1({}, [OBJECT_TYPE]), + // make this null as default don't set this here, only set in the down stream + // serverType: createConfig(null, [STRING_TYPE], {[ENUM_KEY]: AVAILABLE_SERVERS}), + // we require the contract already generated and pass here + contract: createConfig$1({}, [OBJECT_TYPE], ( obj$1 = {}, obj$1[CHECKER_KEY] = isContract, obj$1 )), + enableAuth: createConfig$1(false, [BOOLEAN_TYPE]), + token: createConfig$1(false, [STRING_TYPE]) +}; + +// constant props +var wsCoreConstProps = { + // contract: null, + eventEmitter: null, + // we unify the two different client into one now + // only expect different parameter + nspClient: null, + nspAuthClient: null, + // contructed path + wssPath: '' +}; + +// create options + +/** + * wrapper method to check this already did the pre check + * @param {object} config user supply config + * @param {object} defaultOptions for checking + * @param {object} constProps user supply const props + * @return {promise} resolve to the checked opitons + */ +function checkOptionsWrapper(config, defaultOptions, constProps) { + var wsConstProps = Object.assign(wsCoreConstProps, constProps); + var defaultCheckOptions = Object.assign(wsCoreDefaultOptions, defaultOptions); + /* + const fn = postConfigCheck(checkMap, constProps, checkConfig) + return fn(config) + */ + return checkConfigAsync(config, defaultCheckOptions, wsConstProps) +} + +/** + * Taking the then part from the method below + * @param {object} opts + * @return {promise} opts all done + */ +function postWsOptions(opts) { + return Promise.resolve(opts) + .then(function (opts) { + if (!opts.hostname) { + opts.hostname = getHostName(); + } + // @TODO the contract now will supply the namespace information + // and we need to use that to group the namespace call + opts.wssPath = fixWss([opts.hostname, opts.namespace].join('/'), opts.serverType); + // debug('CONFIGURATION OPTIONS', opts) + return opts + }) +} + +/** + * check the configuration + * @param {object} config user supplied configuration + * @param {object} defaultOptions the check map + * @param {object} constProps developer supplied configuration + * @return {object} after checked + */ +function checkWsCoreOptions(config, defaultOptions, constProps) { + return checkOptionsWrapper(config, defaultOptions, constProps) + .then(postWsOptions) +} + +// the top level API + +/** + * @TODO remove this implmenetation once the test is done + */ +var dummyLogger = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + Reflect.apply(console.info, console, ['[jsonql-ws-client-core]' ].concat( args)); +}; + +/** + * 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; + log('CHECKED_KEY', opts[CHECKED_KEY]); + if (eventEmitter) { + log("eventEmitter is:", eventEmitter.name); + return eventEmitter + } + log("Create a new Event Emitter"); + return new JsonqlWsEvt( opts.log ) +}; + +/** + * 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') { + opts.log = dummyLogger; + } + opts.log('--- wsClientCore config opts ---', opts); + return opts +}; + +/** + * 0.5.0 we break up the wsClientCore in two parts one without the config check + * @param {function} socketClientResolver + * @param {object} config the already checked config + */ +function wsClientCoreAction(socketClientResolver, config) { + return Promise.resolve(config) + .then(getLogFn) + .then(function (opts) { return ({ + opts: opts, + nspMap: processContract(opts), + ee: getEventEmitter(opts) + }); }) + .then( + function (ref) { + var opts = ref.opts; + var nspMap = ref.nspMap; + var ee = ref.ee; + + return socketClientResolver(opts, nspMap, ee); + } + ) + .then( + function (ref) { + var opts = ref.opts; + var nspMap = ref.nspMap; + var ee = ref.ee; + + return generator(opts, nspMap, ee); + } + ) + .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} socketClientResolver this is the one method export by various clients + * @param {object} [defaultOptions={}] 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 {object} the wsClient instance with all the available API + */ +function wsClientCore(socketClientResolver, defaultOptions, constProps) { + if ( defaultOptions === void 0 ) defaultOptions = {}; + if ( constProps === void 0 ) constProps = {}; + + // we need to inject property to this client later + // therefore we need to do it this way + return function (config) { + if ( config === void 0 ) config = {}; + + return ( + checkWsCoreOptions(config, defaultOptions, constProps) + .then(function (opts) { return wsClientCoreAction(socketClientResolver, opts); }) + ); + } + +} + +// jsonql-ws-core takes over the check configuration +// constant props +var wsClientConstProps = { + version: 'version: 1.1.0 module: cjs', // will get replace + serverType: JS_WS_NAME +}; + +var wsClientAppProps = {}; + +// pass the different type of ws to generate the client +/** + * WebSocket is strict about the path, therefore we need to make sure before it goes in + * @param {string} url input url + * @return {string} url with correct path name + */ +var fixWss$1 = function (url) { + var uri = url.toLowerCase(); + if (uri.indexOf('http') > -1) { + if (uri.indexOf('https') > -1) { + return uri.replace('https', 'wss') + } + return uri.replace('http', 'ws') + } + return uri +}; + +/** + * The bug was in the wsOptions where ws doesn't need it but socket.io do + * therefore the object was pass as second parameter! + * @param {object} WebSocket the client or node version of ws + * @param {boolean} auth if it's auth then 3 param or just one + */ +function createWsClient(WebSocket, auth) { + if ( auth === void 0 ) auth = false; + + if (auth === false) { + return function createWsClientHandler(url) { + return new WebSocket(fixWss$1(url)) + } + } + + /** + * Create a client with auth token + * @param {string} url start with ws:// @TODO check this? + * @param {string} token the jwt token + * @return {object} ws instance + */ + return function createWsAuthClientHandler(url, token) { + var ws_url = fixWss$1(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 + } + } +} + +// since both the ws and io version are +// pre-defined in the client-generator +// and this one will have the same parameters +// and the callback is identical + +/** + * wrapper method to create a nsp without login + * @param {string|boolean} namespace namespace url could be false + * @param {object} opts configuration + * @return {object} ws client instance + */ +function createNspClient(namespace, opts) { + var hostname = opts.hostname; + var wssPath = opts.wssPath; + var wsOptions = opts.wsOptions; + var nspClient = opts.nspClient; + var url = namespace ? [hostname, namespace].join('/') : wssPath; + return nspClient(url, wsOptions) +} + +/** + * wrapper method to create a nsp with token auth + * @param {string} namespace namespace url + * @param {object} opts configuration + * @return {object} ws client instance + */ +function createNspAuthClient(namespace, opts) { + var hostname = opts.hostname; + var wssPath = opts.wssPath; + var token = opts.token; + var wsOptions = opts.wsOptions; + var nspAuthClient = opts.nspAuthClient; + var url = namespace ? [hostname, namespace].join('/') : wssPath; + if (token && typeof token !== 'string') { + throw new Error(("Expect token to be string, but got " + token)) + } + return nspAuthClient(url, token, wsOptions) +} + +// 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 + * @param {object} opts configuration + * @return {void} + */ +function triggerNamespacesOnError(ee, namespaces, message, opts) { + if ( opts === void 0 ) opts = {}; + + var useCallbackStyle = opts.useCallbackStyle; + var ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME; + namespaces.forEach( function (namespace) { + ee.$call(createEvt(namespace, ERROR_SUBFIX), [{ message: message, namespace: namespace }]); + }); +} + +// This is share between different clients so we export it + +/** + * A fake ee handler + * @param {string} namespace nsp + * @param {object} ee EventEmitter + * @param {object} opts configuration + * @return {void} + */ +var notLoginWsHandler = function (namespace, ee, opts) { + var useCallbackStyle = opts.useCallbackStyle; + var log = opts.log; + var ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME; + var RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME; + ee.$only( + createEvt(namespace, EMIT_EVT), + function notLoginHandlerCallback(resolverName, args) { + + log('[notLoginHandler] 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, ERROR_SUBFIX), [error]); + // also trigger the result handler, but wrap inside the error key + ee.$call(createEvt(namespace, resolverName, RESULT_SUBFIX), [{ 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 +); }; + +/** + * centralize all the comm in one place + * @param {object} opts configuration + * @param {array} namespaces namespace(s) + * @param {object} ee Event Emitter instance + * @param {function} bindWsHandler binding the ee to ws --> this is the core bit + * @param {array} namespaces array of namespace available + * @param {object} nsps namespaced nsp + * @return {void} nothing + */ +function clientEventHandler(opts, nspMap, ee, bindWsHandler, namespaces, nsps) { + // @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 log = opts.log; + // 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 a waterfall here to make sure + // one is execute then the other + namespaces.forEach(function (namespace) { + isPrivate = privateNamespace === namespace; + if (nsps[namespace]) { + log('[call bindWsHandler]', isPrivate, namespace); + var args = [namespace, nsps[namespace], ee, isPrivate, opts]; + if (opts.serverType === SOCKET_IO) { + var nspSet = nspMap.nspSet; + args.push(nspSet[namespace]); + } + Reflect.apply(bindWsHandler, null, args); + } else { + // a dummy placeholder + notLoginWsHandler(namespace, ee, opts); + } + }); + // this will be available regardless enableAuth + // because the server can log the client out + ee.$on(LOGOUT_EVENT_NAME, function logoutEvtHandler() { + log('LOGOUT_EVENT_NAME'); + // disconnect(nsps, opts.serverType) + // we need to issue error to all the namespace onError handler + triggerNamespacesOnError(ee, namespaces, LOGOUT_EVENT_NAME); + // rebind all of the handler to the fake one + namespaces.forEach( function (namespace) { + clearMainEmitEvt(ee, namespace); + // clear out the nsp + nsps[namespace] = false; + // add a NOT LOGIN error if call + notLoginWsHandler(namespace, ee, opts); + }); + }); +} + +// take the ws reply data for use + +var keys$1 = [ WS_REPLY_TYPE, WS_EVT_NAME, WS_DATA_NAME ]; + +/** + * @param {object} payload should be string when reply but could be transformed + * @return {boolean} true is OK + */ +var isWsReply = function (payload) { + var data = payload.data; + if (data) { + var result = keys$1.filter(function (key) { return isObjectHasKey$1(data, key); }); + return (result.length === keys$1.length) ? data : false + } + return false +}; + +/** + * @param {object} payload This is the entire ws Event Object + * @return {object} false on failed + */ +var extractWsPayload = function (payload) { + var data = payload.data; + var json = isString$1(data) ? JSON.parse(data) : data; + var fdata; + if ((fdata = isWsReply(json)) !== false) { + return { + resolverName: fdata[WS_EVT_NAME], + data: fdata[WS_DATA_NAME], + type: fdata[WS_REPLY_TYPE] + } + } + throw new JsonqlError('payload can not be decoded', payload) +}; + +// the WebSocket main handler + + +/** + * under extremely circumstances we might not even have a resolverName, then + * we issue a global error for the developer to catch it + * @param {object} ee event emitter + * @param {string} namespace nsp + * @param {string} resolverName resolver + * @param {object} json decoded payload or error object + * @param {string} ERROR_EVT_NAME the error event name + * @return {undefined} nothing return + */ +var errorTypeHandler = function (ee, namespace, resolverName, json, ERROR_EVT_NAME) { + var evt = [namespace]; + if (resolverName) { + evt.push(resolverName); + } + evt.push(ERROR_EVT_NAME); + var evtName = Reflect.apply(createEvt, null, evt); + // test if there is a data field + var payload = json.data || json; + ee.$trigger(evtName, [payload]); +}; + +/** + * Binding the even to socket normally + * @param {string} namespace + * @param {object} ws the nsp + * @param {object} ee EventEmitter + * @param {boolean} isPrivate to id if this namespace is private or not + * @param {object} opts configuration + * @return {object} promise resolve after the onopen event + */ +function wsMainHandler(namespace, ws, ee, isPrivate, opts) { + var useCallbackStyle = opts.useCallbackStyle; + var log = opts.log; + + log("wsMainHandler log test"); + + var READY_EVT_NAME = useCallbackStyle ? READY_PROP_NAME : ON_READY_PROP_NAME; + var LOGIN_EVT_NAME = useCallbackStyle ? LOGIN_PROP_NAME : ON_LOGIN_PROP_NAME; + var MESSAGE_EVT_NAME = useCallbackStyle ? MESSAGE_PROP_NAME : ON_MESSAGE_PROP_NAME; + var RESULT_EVT_NAME = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME; + var ERROR_EVT_NAME = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME; + // connection open + ws.onopen = function onOpenCallback() { + log('ws.onopen listened'); + // we just call the onReady + ee.$call(READY_EVT_NAME, namespace); + // need an extra parameter here to id the private nsp + if (isPrivate) { + log(("isPrivate and fire the " + LOGIN_EVT_NAME)); + ee.$call(LOGIN_EVT_NAME, namespace); + } + // add listener only after the open is called + ee.$only( + createEvt(namespace, EMIT_REPLY_TYPE), + function wsMainOnEvtHandler(resolverName, args) { + log('calling server', resolverName, args); + ws.send( + createQueryStr(resolverName, args) + ); + } + ); + }; + + // reply + // If we change it to the event callback style + // then the payload will just be the payload and fucks up the extractWsPayload call @TODO + ws.onmessage = function onMessageCallback(payload) { + // console.log(`on.message`, typeof payload, payload) + try { + var json = extractWsPayload(payload); + var resolverName = json.resolverName; + var type = json.type; + log('Hear from server', type, json); + switch (type) { + case EMIT_REPLY_TYPE: + var e1 = createEvt(namespace, resolverName, MESSAGE_EVT_NAME); + var r = ee.$trigger(e1, [json]); + log("EMIT_REPLY_TYPE", e1, r); + break; + case ACKNOWLEDGE_REPLY_TYPE: + var e2 = createEvt(namespace, resolverName, RESULT_EVT_NAME); + var x = ee.$trigger(e2, [json]); + // log(`ACKNOWLEDGE_REPLY_TYPE`, e2, json) + break; + case ERROR_TYPE: + // this is handled error and we won't throw it + // we need to extract the error from json + log("ERROR_TYPE"); + errorTypeHandler(ee, namespace, resolverName, json, ERROR_EVT_NAME); + break; + // @TODO there should be an error type instead of roll into the other two types? TBC + default: + // if this happen then we should throw it and halt the operation all together + log('Unhandled event!', json); + errorTypeHandler(ee, namespace, resolverName, json, ERROR_EVT_NAME); + // let error = {error: {'message': 'Unhandled event!', type}}; + // ee.$trigger(createEvt(namespace, resolverName, ON_RESULT_PROP_NAME), [error]) + } + } catch(e) { + console.error("ws.onmessage error", e); + errorTypeHandler(ee, namespace, false, e, ERROR_EVT_NAME); + } + }; + // when the server close the connection + ws.onclose = function onCloseCallback() { + log('ws.onclose callback'); + // @TODO what to do with this + // ee.$trigger(LOGOUT_EVENT_NAME, [namespace]) + }; + // listen to the LOGOUT_EVENT_NAME + ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() { + try { + log('terminate ws connection'); + ws.terminate(); + } catch(e) { + console.error('ws.terminate error', e); + } + }); +} + +// actually binding the event client to the socket client + +/** + * 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 createNsps = function(opts, nspMap, token) { + var nspSet = nspMap.nspSet; + var publicNamespace = nspMap.publicNamespace; + var login = false; + var namespaces = []; + var nsps = {}; + // first we need to binding all the events handler + if (opts.enableAuth) { // && opts.useJwt + login = true; // just saying we need to listen to login event + namespaces = getNamespaceInOrder(nspSet, publicNamespace); + nsps = namespaces.map(function (namespace, i) { + var obj, obj$1, obj$2; + + if (i === 0) { + if (token) { + opts.token = token; + // console.log('create createNspAuthClient at run time', opts) + 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); }, {}); + } else { + var namespace = getNameFromPayload(nspSet); + namespaces.push(namespace); + // standard without login + // the stock version should not have a namespace + nsps[namespace] = createNspClient(false, opts); + } + // return + return { nsps: nsps, namespaces: namespaces, login: login } +}; + +/** + * create a ws client + * @param {object} opts configuration + * @param {object} nspMap namespace with resolvers + * @param {object} ee EventEmitter to pass through + * @return {object} what comes in what goes out + */ +function createClient(opts, nspMap, ee) { + // arguments that don't change + var args = [opts, nspMap, ee, wsMainHandler]; + // now create the nsps + var token = opts.token; + var log = opts.log; + var ref = createNsps(opts, nspMap, token); + var nsps = ref.nsps; + var namespaces = ref.namespaces; + var login = ref.login; + // 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.concat([namespaces, nsps])); + // setup listener + if (login) { + ee.$only(LOGIN_EVENT_NAME, function loginEventHandler(tokenLater) { + + log('createClient LOGIN_EVENT_NAME'); + + // debugFn(`LOGIN_EVENT_NAME called with token:`, tokenLater) + // @BUG this keep causing an "Disconnect call failed TypeError: Cannot read property 'readyState' of null" + // I think that is because it's not login then it can not be disconnect + // how do we track this state globally + // disconnect(nsps, JS_WS_NAME) + + // @TODO should we trigger error on this one? + // triggerNamespacesOnError(ee, namespaces, LOGIN_EVENT_NAME) + clearMainEmitEvt(ee, namespaces); + // console.log('LOGIN_EVENT_NAME', token) + var newNsps = createNsps(opts, nspMap, tokenLater); + // rebind it + Reflect.apply( + clientEventHandler, + null, + args.concat([newNsps.namespaces, newNsps.nsps]) + ); + }); + } + // return what input + return { opts: opts, nspMap: nspMap, ee: ee } +} + +// share method to create the wsClientResolver + +/** + * combine the create client resolver + * @param {object} ws the different WebSocket module + * @return {function} the wsClientResolver + */ +function createClientResolver(ws) { + var client = createWsClient(ws); + var authClient = createWsClient(ws, true); + /** + * wsClientResolver + * @param {object} opts configuration + * @param {object} nspMap from the contract + * @param {object} ee instance of the eventEmitter + * @return {object} passing the same 3 input out with additional in the opts + */ + return function(opts, nspMap, ee) { + opts.nspClient = client; + opts.nspAuthClient = authClient; + // @1.0.7 remove later once everything fixed + var log = opts.log; + if (log && typeof log === 'function') { + log('@jsonql/ws ee', ee.name); + log('@jsonql/ws createClientResolver', opts); + } + // console.log(`contract`, opts.contract) + return createClient(opts, nspMap, ee) + } +} + +// this will be the news style interface that will pass to the jsonql-ws-client + +/** + * @param {object} opts configuration + * @param {object} nspMap from the contract + * @param {object} ee instance of the eventEmitter + * @return {object} passing the same 3 input out with additional in the opts + */ +var wsClientResolver = createClientResolver(WebSocket); + +// this is the module entry point for node + +// export back the function and that's it +function wsBrowserClient(config, constProps) { + if ( config === void 0 ) config = {}; + if ( constProps === void 0 ) constProps = {}; + + var initMethod = wsClientCore(wsClientResolver, wsClientAppProps, Object.assign(wsClientConstProps, constProps)); + return initMethod(config) +} + +module.exports = wsBrowserClient; //# sourceMappingURL=main.js.map diff --git a/packages/@jsonql/ws/main.js.map b/packages/@jsonql/ws/main.js.map index aee0a927..0bfeb3eb 100644 --- a/packages/@jsonql/ws/main.js.map +++ b/packages/@jsonql/ws/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","sources":[],"sourcesContent":[],"names":[],"mappings":""} \ No newline at end of file +{"version":3,"file":"main.js","sources":["node_modules/jsonql-errors/src/500-error.js","node_modules/jsonql-errors/src/resolver-not-found-error.js","node_modules/jsonql-errors/src/enum-error.js","node_modules/jsonql-errors/src/type-error.js","node_modules/jsonql-errors/src/checker-error.js","node_modules/jsonql-errors/src/validation-error.js","node_modules/jsonql-errors/src/server-error.js","node_modules/jsonql-ws-client-core/src/options/constants.js","node_modules/rollup-plugin-node-globals/src/global.js","node_modules/lodash-es/_arrayMap.js","node_modules/lodash-es/isArray.js","node_modules/lodash-es/_objectToString.js","node_modules/lodash-es/isObjectLike.js","node_modules/lodash-es/_baseSlice.js","node_modules/lodash-es/_baseFindIndex.js","node_modules/lodash-es/_baseIsNaN.js","node_modules/lodash-es/_strictIndexOf.js","node_modules/lodash-es/_asciiToArray.js","node_modules/lodash-es/_hasUnicode.js","node_modules/lodash-es/_unicodeToArray.js","node_modules/jsonql-params-validator/src/number.js","node_modules/jsonql-params-validator/src/string.js","node_modules/jsonql-params-validator/src/boolean.js","node_modules/jsonql-params-validator/src/any.js","node_modules/jsonql-params-validator/src/constants.js","node_modules/jsonql-params-validator/src/combine.js","node_modules/jsonql-params-validator/src/array.js","node_modules/lodash-es/_overArg.js","node_modules/lodash-es/_arrayFilter.js","node_modules/lodash-es/_createBaseFor.js","node_modules/lodash-es/_baseTimes.js","node_modules/lodash-es/stubFalse.js","node_modules/lodash-es/_isIndex.js","node_modules/lodash-es/isLength.js","node_modules/lodash-es/_baseUnary.js","node_modules/lodash-es/_isPrototype.js","node_modules/lodash-es/isObject.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/_toSource.js","node_modules/lodash-es/_getValue.js","node_modules/lodash-es/_hashDelete.js","node_modules/lodash-es/_isKeyable.js","node_modules/lodash-es/_setCacheAdd.js","node_modules/lodash-es/_setCacheHas.js","node_modules/lodash-es/_arraySome.js","node_modules/lodash-es/_cacheHas.js","node_modules/lodash-es/_mapToArray.js","node_modules/lodash-es/_setToArray.js","node_modules/lodash-es/_arrayPush.js","node_modules/lodash-es/stubArray.js","node_modules/lodash-es/_matchesStrictComparable.js","node_modules/lodash-es/_baseHasIn.js","node_modules/lodash-es/identity.js","node_modules/lodash-es/_baseProperty.js","node_modules/jsonql-params-validator/src/object.js","node_modules/jsonql-params-validator/src/validator.js","node_modules/lodash-es/_copyArray.js","node_modules/lodash-es/_safeGet.js","node_modules/lodash-es/_nativeKeysIn.js","node_modules/lodash-es/_apply.js","node_modules/lodash-es/constant.js","node_modules/lodash-es/_shortOut.js","node_modules/lodash-es/negate.js","node_modules/lodash-es/_baseFindKey.js","node_modules/jsonql-params-validator/src/is-in-array.js","node_modules/jsonql-params-validator/src/options/run-validation.js","node_modules/jsonql-params-validator/src/options/check-options-async.js","node_modules/jsonql-params-validator/src/options/construct-config.js","node_modules/jsonql-params-validator/src/options/index.js","node_modules/jsonql-params-validator/index.js","node_modules/jsonql-utils/src/generic.js","node_modules/jsonql-utils/src/chain-promises.js","node_modules/jsonql-utils/src/contract.js","node_modules/jsonql-utils/src/timestamp.js","node_modules/jsonql-utils/src/params-api.js","node_modules/nb-event-service/src/hash-code.js","node_modules/nb-event-service/src/suspend.js","node_modules/nb-event-service/src/store-service.js","node_modules/nb-event-service/src/event-service.js","node_modules/nb-event-service/index.js","node_modules/jsonql-ws-client-core/src/utils/ee.js","node_modules/jsonql-ws-client-core/src/utils/process-contract.js","node_modules/jsonql-ws-client-core/src/utils/helpers.js","node_modules/jsonql-ws-client-core/src/core/respond-handler.js","node_modules/jsonql-ws-client-core/src/core/action-call.js","node_modules/jsonql-ws-client-core/src/core/setup-callback-api.js","node_modules/jsonql-ws-client-core/src/core/setup-resolver.js","node_modules/jsonql-ws-client-core/src/core/resolver-methods.js","node_modules/jsonql-ws-client-core/src/core/setup-auth-methods.js","node_modules/jsonql-ws-client-core/src/core/generator.js","node_modules/jsonql-ws-client-core/src/options/index.js","node_modules/jsonql-ws-client-core/src/api.js","src/options/index.js","src/core/create-ws-client.js","node_modules/jsonql-ws-client-core/src/share/create-nsp-client.js","node_modules/jsonql-ws-client-core/src/share/trigger-namespaces-on-error.js","node_modules/jsonql-ws-client-core/src/share/client-event-handler.js","src/core/extract-ws-payload.js","src/core/ws-main-handler.js","src/core/create-client.js","src/core/create-client-resolver.js","src/node-ws-client-resolver.js","src/node.js"],"sourcesContent":["/**\n * This is a custom error to throw when server throw a 500\n * This help us to capture the right error, due to the call happens in sequence\n * @param {string} message to tell what happen\n * @param {mixed} extra things we want to add, 500?\n */\nexport default class Jsonql500Error extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = Jsonql500Error.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, Jsonql500Error)\n }\n }\n\n static get statusCode() {\n return 500;\n }\n\n static get name() {\n return 'Jsonql500Error';\n }\n\n}\n","/**\n * This is a custom error to throw when could not find the resolver\n * This help us to capture the right error, due to the call happens in sequence\n * @param {string} message to tell what happen\n * @param {mixed} extra things we want to add, 500?\n */\nexport default class JsonqlResolverNotFoundError extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlResolverNotFoundError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlResolverNotFoundError);\n }\n }\n\n static get statusCode() {\n return 404;\n }\n\n static get name() {\n return 'JsonqlResolverNotFoundError';\n }\n}\n","// this get throw from within the checkOptions when run through the enum failed\nexport default class JsonqlEnumError extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlEnumError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlEnumError);\n }\n }\n\n static get name() {\n return 'JsonqlEnumError';\n }\n}\n","// this will throw from inside the checkOptions\nexport default class JsonqlTypeError extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlTypeError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlTypeError);\n }\n }\n\n static get name() {\n return 'JsonqlTypeError';\n }\n}\n","// allow supply a custom checker function\n// if that failed then we throw this error\nexport default class JsonqlCheckerError extends Error {\n constructor(...args) {\n super(...args)\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlCheckerError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlCheckerError)\n }\n }\n\n static get name() {\n return 'JsonqlCheckerError';\n }\n}\n","// custom validation error class\n// when validaton failed\nexport default class JsonqlValidationError extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlValidationError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlValidationError)\n }\n }\n\n static get name() {\n return 'JsonqlValidationError';\n }\n}\n","// this is from an example from Koa team to use for internal middleware ctx.throw\n// but after the test the res.body part is unable to extract the required data\n// I keep this one here for future reference\n\nexport default class JsonqlServerError extends Error {\n\n constructor(statusCode, message) {\n super(message)\n this.statusCode = statusCode;\n this.className = JsonqlServerError.name;\n }\n\n static get name() {\n return 'JsonqlServerError';\n }\n}\n","// constants\n\nimport {\n EMIT_REPLY_TYPE,\n JS_WS_SOCKET_IO_NAME,\n JS_WS_NAME,\n ON_MESSAGE_PROP_NAME,\n ON_RESULT_PROP_NAME\n} from 'jsonql-constants'\n\nconst SOCKET_IO = JS_WS_SOCKET_IO_NAME;\nconst WS = JS_WS_NAME;\n\nconst AVAILABLE_SERVERS = [SOCKET_IO, WS]\n\nconst SOCKET_NOT_DEFINE_ERR = 'socket is not define in the contract file!';\n\nconst SERVER_NOT_SUPPORT_ERR = 'is not supported server name!';\n\nconst MISSING_PROP_ERR = 'Missing property in contract!';\n\nconst UNKNOWN_CLIENT_ERR = 'Unknown client type!';\n\nconst EMIT_EVT = EMIT_REPLY_TYPE;\n\nconst NAMESPACE_KEY = 'namespaceMap';\n\nconst UNKNOWN_RESULT = 'UKNNOWN RESULT!';\n\nconst NOT_ALLOW_OP = 'This operation is not allow!';\n\nconst MY_NAMESPACE = 'myNamespace'\n\nconst CB_FN_NAME = 'on'\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_PROP_NAME,\n ON_RESULT_PROP_NAME,\n NAMESPACE_KEY,\n UNKNOWN_RESULT,\n NOT_ALLOW_OP,\n MY_NAMESPACE,\n CB_FN_NAME\n}\n","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\nexport const ARGS_NOT_ARRAY_ERR = `args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)`;\nexport const PARAMS_NOT_ARRAY_ERR = `params is not an array! Did something gone wrong when you generate the contract.json?`;\nexport const EXCEPTION_CASE_ERR = 'Could not understand your arguments and parameter structure!';\nexport const UNUSUAL_CASE_ERR = 'This is an unusual situation where the arguments are more than the params, but not mark as spread';\n\n// re-export\nimport * as JSONQL_CONSTANTS from 'jsonql-constants';\n// @TODO the jsdoc return array. and we should also allow array syntax\nexport const DEFAULT_TYPE = JSONQL_CONSTANTS.DEFAULT_TYPE;\nexport const ARRAY_TYPE_LFT = JSONQL_CONSTANTS.ARRAY_TYPE_LFT;\nexport const ARRAY_TYPE_RGT = JSONQL_CONSTANTS.ARRAY_TYPE_RGT;\n\nexport const TYPE_KEY = JSONQL_CONSTANTS.TYPE_KEY;\nexport const OPTIONAL_KEY = JSONQL_CONSTANTS.OPTIONAL_KEY;\nexport const ENUM_KEY = JSONQL_CONSTANTS.ENUM_KEY;\nexport const ARGS_KEY = JSONQL_CONSTANTS.ARGS_KEY;\nexport const CHECKER_KEY = JSONQL_CONSTANTS.CHECKER_KEY;\nexport const ALIAS_KEY = JSONQL_CONSTANTS.ALIAS_KEY;\n\nexport const ARRAY_TYPE = JSONQL_CONSTANTS.ARRAY_TYPE;\nexport const OBJECT_TYPE = JSONQL_CONSTANTS.OBJECT_TYPE;\nexport const STRING_TYPE = JSONQL_CONSTANTS.STRING_TYPE;\nexport const BOOLEAN_TYPE = JSONQL_CONSTANTS.BOOLEAN_TYPE;\nexport const NUMBER_TYPE = JSONQL_CONSTANTS.NUMBER_TYPE;\nexport const KEY_WORD = JSONQL_CONSTANTS.KEY_WORD;\nexport const OR_SEPERATOR = JSONQL_CONSTANTS.OR_SEPERATOR;\n\n// not actually in use\n// export const NUMBER_TYPES = JSONQL_CONSTANTS.NUMBER_TYPES;\n","// primitive types\nimport checkIsNumber from './number'\nimport checkIsString from './string'\nimport checkIsBoolean from './boolean'\nimport checkIsAny from './any'\nimport { NUMBER_TYPE, STRING_TYPE, BOOLEAN_TYPE } from './constants'\n\n/**\n * this is a wrapper method to call different one based on their type\n * @param {string} type to check\n * @return {function} a function to handle the type\n */\nconst combineFn = function(type) {\n switch (type) {\n case NUMBER_TYPE:\n return checkIsNumber;\n case STRING_TYPE:\n return checkIsString;\n case BOOLEAN_TYPE:\n return checkIsBoolean;\n default:\n return checkIsAny;\n }\n}\n\nexport default combineFn\n","// validate array type\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","/**\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 * 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 * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\nexport default baseTimes;\n","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n return false;\n}\n\nexport default stubFalse;\n","/** 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","/** 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 * 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","/** 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 the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nexport default isObject;\n","/**\n * 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","/** 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","/** 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 * 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 * 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 * 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","// validate object type\n\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport filter from 'lodash-es/filter'\n\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 checkIsObject,\n combineFn,\n notEmpty\n} from './index'\nimport {\n DEFAULT_TYPE,\n ARRAY_TYPE,\n OBJECT_TYPE,\n ARGS_NOT_ARRAY_ERR,\n PARAMS_NOT_ARRAY_ERR,\n EXCEPTION_CASE_ERR,\n UNUSUAL_CASE_ERR\n} from './constants'\nimport { DATA_KEY, ERROR_KEY } from 'jsonql-constants'\nimport { JsonqlError } from 'jsonql-errors'\n// 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 JsonqlError(PARAMS_NOT_ARRAY_ERR)\n }\n if (params.length === 0) {\n return [];\n }\n if (!checkIsArray(args)) {\n throw new JsonqlError(ARGS_NOT_ARRAY_ERR)\n }\n // debugFn(args, params);\n // fall through switch\n switch(true) {\n case args.length == params.length: // standard\n return args.map((arg, i) => (\n {\n arg,\n index: i,\n param: params[i]\n }\n ))\n case params[0].variable === true: // using spread syntax\n const type = params[0].type;\n return args.map((arg, i) => (\n {\n arg,\n index: i, // keep the index for reference\n param: params[i] || { type, name: '_' }\n }\n ))\n // with optional defaultValue parameters\n case args.length < params.length:\n return params.map((param, i) => (\n {\n param,\n index: i,\n arg: getOptionalValue(args[i], param),\n optional: param.optional || false\n }\n ))\n // this one pass more than it should have anything after the args.length will be cast as any type\n case args.length > params.length:\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 * 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","/**\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 * 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 * 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","/** 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'\nimport 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'\n// PIA syntax\nexport const isObject = checkIsObject;\nexport const isAny = checkIsAny;\nexport const isString = checkIsString;\nexport const isBoolean = checkIsBoolean;\nexport const isNumber = checkIsNumber;\nexport const isArray = checkIsArray;\nexport const isNotEmpty = notEmpty;\n\nimport * as validator from './src/validator'\n\nexport const normalizeArgs = validator.normalizeArgs;\nexport const validateSync = validator.validateSync;\nexport const validateAsync = validator.validateAsync;\n\n// configuration checking\n\nimport * as jsonqlOptions from './src/options'\n\nexport const JSONQL_PARAMS_VALIDATOR_INFO = jsonqlOptions.JSONQL_PARAMS_VALIDATOR_INFO;\n\nexport const createConfig = jsonqlOptions.createConfig;\nexport const constructConfig = jsonqlOptions.constructConfigFn;\n// construct the final output 1.5.2\nexport const checkConfigAsync = jsonqlOptions.getCheckConfigAsync(validator.validateSync)\nexport const checkConfig = jsonqlOptions.getCheckConfig(validator.validateSync)\n\n// export the two extra functions\nimport isInArray from './src/is-in-array'\nimport isObjectHasKeyFn from './src/options/is-key-in-object'\n\nexport const inArray = isInArray;\nexport const isObjectHasKey = isObjectHasKeyFn;\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 * @return {*} json object on success\n */\nconst parse = function(n) {\n try {\n return JSON.parse(n)\n } catch(e) {\n return n;\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 console.info('obj', obj)\n console.error(e)\n throw new Error(e)\n */\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 parse(n)\n }\n return JSON.parse(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","// 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","// 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')) {\n return contract.socket;\n }\n return false;\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 * @param {boolean} [fallback=false] this is a fall back option for old code\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, fallback = false) {\n let socket = extractSocketPart(contract)\n if (socket === false) {\n if (fallback) {\n return contract; // just return the whole contract\n }\n throw new JsonqlError(`socket not found in contract!`)\n }\n let nspSet = {};\n let size = 0;\n let publicNamespace;\n for (let resolverName in socket) {\n let params = socket[resolverName];\n let { namespace } = params;\n if (namespace) {\n if (!nspSet[namespace]) {\n ++size;\n nspSet[namespace] = {};\n }\n nspSet[namespace][resolverName] = params;\n if (!publicNamespace) {\n if (params.public) {\n publicNamespace = namespace;\n }\n }\n }\n }\n return { size, nspSet, publicNamespace }\n}\n\n/**\n * @NOTE ported from jsonql-ws-client\n * Got to make sure the connection order otherwise\n * it will hang\n * @param {object} nspSet contract\n * @param {string} publicNamespace like the name said\n * @return {array} namespaces in order\n */\nexport function getNamespaceInOrder(nspSet, publicNamespace) {\n let names = []; // need to make sure the order!\n for (let namespace in nspSet) {\n if (namespace === publicNamespace) {\n names[1] = namespace;\n } else {\n names[0] = namespace;\n }\n }\n return names;\n}\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'\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\n\nimport isArray from 'lodash-es/isArray'\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport isString from 'lodash-es/isString'\n\nimport { timestamp } from './timestamp'\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) ? JSON.parse(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 * Get name from the payload (ported back from jsonql-koa)\n * @param {*} payload to extract from\n * @return {string} name\n */\nexport function getNameFromPayload(payload) {\n return Object.keys(payload)[0]\n}\n\n/**\n * 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]: payload[TIMESTAMP_PARAM_NAME]\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 = getNameFromPayload(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]: payload[TIMESTAMP_PARAM_NAME]\n }\n }\n }\n return false;\n}\n\n/**\n * @param {object} payload\n * @return {object} resolverName, payload, conditon\n */\nexport function getMutationFromPayload(payload) {\n const result = processPayload(payload, getMutationFromArgs)\n\n if (result !== false) {\n return result;\n }\n throw new JsonqlValidationError('[getMutationArgs] Payload is malformed!', payload)\n}\n","/**\n * generate a 32bit hash based on the function.toString()\n * _from http://stackoverflow.com/questions/7616461/generate-a-hash-_from-string-in-javascript-jquery\n * @param {string} s the converted to string function\n * @return {string} the hashed function string\n */\nexport function hashCode(s) {\n\treturn s.split(\"\").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0)\n}\n// wrapper to make sure it string \nexport function hashCode2Str(s) {\n return hashCode(s) + ''\n}\n","// making all the functionality on it's own\n// import { WatchClass } from './watch'\n\nexport default class SuspendClass {\n\n constructor() {\n // suspend, release and queue\n this.__suspend__ = null;\n this.queueStore = new Set()\n /*\n this.watch('suspend', function(value, prop, oldValue) {\n this.logger(`${prop} set from ${oldValue} to ${value}`)\n // it means it set the suspend = true then release it\n if (oldValue === true && value === false) {\n // we want this happen after the return happens\n setTimeout(() => {\n this.release()\n }, 1)\n }\n return value; // we need to return the value to store it\n })\n */\n }\n\n /**\n * setter to set the suspend and check if it's boolean value\n * @param {boolean} value to trigger\n */\n set $suspend(value) {\n if (typeof value === 'boolean') {\n const lastValue = this.__suspend__;\n this.__suspend__ = value;\n this.logger('($suspend)', `Change from ${lastValue} --> ${value}`)\n if (lastValue === true && value === false) {\n setTimeout(() => {\n this.release()\n }, 1)\n }\n } else {\n throw new Error(`$suspend only accept Boolean value!`)\n }\n }\n\n /**\n * queuing call up when it's in suspend mode\n * @param {any} value\n * @return {Boolean} true when added or false when it's not\n */\n $queue(...args) {\n if (this.__suspend__ === true) {\n this.logger('($queue)', 'added to $queue', args)\n // there shouldn't be any duplicate ...\n this.queueStore.add(args)\n }\n return this.__suspend__;\n }\n\n /**\n * a getter to get all the store queue\n * @return {array} Set turn into Array before return\n */\n get $queues() {\n let size = this.queueStore.size;\n this.logger('($queues)', `size: ${size}`)\n if (size > 0) {\n return Array.from(this.queueStore)\n }\n return []\n }\n\n /**\n * Release the queue\n * @return {int} size if any\n */\n release() {\n let size = this.queueStore.size\n this.logger('(release)', `Release was called ${size}`)\n if (size > 0) {\n const queue = Array.from(this.queueStore)\n this.queueStore.clear()\n this.logger('queue', queue)\n queue.forEach(args => {\n this.logger(args)\n Reflect.apply(this.$trigger, this, args)\n })\n this.logger(`Release size ${this.queueStore.size}`)\n }\n }\n}\n","// break up the main file because its getting way too long\nimport {\n NB_EVENT_SERVICE_PRIVATE_STORE,\n NB_EVENT_SERVICE_PRIVATE_LAZY\n} from './store'\nimport { hashCode2Str } from './hash-code'\nimport SuspendClass from './suspend'\n\nexport default class NbEventServiceBase extends SuspendClass {\n\n constructor(config = {}) {\n super()\n if (config.logger && typeof config.logger === 'function') {\n this.logger = config.logger;\n }\n this.keep = config.keep;\n // for the $done setter\n this.result = config.keep ? [] : null;\n // we need to init the store first otherwise it could be a lot of checking later\n this.normalStore = new Map()\n this.lazyStore = new Map()\n }\n\n // for id if the instance is this class\n get is() {\n return 'nb-event-service'\n }\n\n /**\n * validate the event name(s)\n * @param {string[]} evt event name\n * @return {boolean} true when OK\n */\n validateEvt(...evt) {\n evt.forEach(e => {\n if (typeof e !== 'string') {\n this.logger('(validateEvt)', e)\n throw new Error(`event name must be string type!`)\n }\n })\n return true;\n }\n\n /**\n * Simple quick check on the two main parameters\n * @param {string} evt event name\n * @param {function} callback function to call\n * @return {boolean} true when OK\n */\n validate(evt, callback) {\n if (this.validateEvt(evt)) {\n if (typeof callback === 'function') {\n return true;\n }\n }\n throw new Error(`callback required to be function type!`)\n }\n\n /**\n * Check if this type is correct or not added in V1.5.0\n * @param {string} type for checking\n * @return {boolean} true on OK\n */\n validateType(type) {\n const types = ['on', 'only', 'once', 'onlyOnce']\n return !!types.filter(t => type === t).length;\n }\n\n /**\n * Run the callback\n * @param {function} callback function to execute\n * @param {array} payload for callback\n * @param {object} ctx context or null\n * @return {void} the result store in $done\n */\n run(callback, payload, ctx) {\n this.logger('(run)', callback, payload, ctx)\n this.$done = Reflect.apply(callback, ctx, this.toArray(payload))\n }\n\n /**\n * Take the content out and remove it from store id by the name\n * @param {string} evt event name\n * @param {string} [storeName = lazyStore] name of store\n * @return {object|boolean} content or false on not found\n */\n takeFromStore(evt, storeName = 'lazyStore') {\n let store = this[storeName] // it could be empty at this point\n if (store) {\n this.logger('(takeFromStore)', storeName, store)\n if (store.has(evt)) {\n let content = store.get(evt)\n this.logger('(takeFromStore)', `has ${evt}`, content)\n store.delete(evt)\n return content;\n }\n return false;\n }\n throw new Error(`${storeName} is not supported!`)\n }\n\n /**\n * The add to store step is similar so make it generic for resuse\n * @param {object} store which store to use\n * @param {string} evt event name\n * @param {spread} args because the lazy store and normal store store different things\n * @return {array} store and the size of the store\n */\n addToStore(store, evt, ...args) {\n let fnSet;\n if (store.has(evt)) {\n this.logger('(addToStore)', `${evt} existed`)\n fnSet = store.get(evt)\n } else {\n this.logger('(addToStore)', `create new Set for ${evt}`)\n // this is new\n fnSet = new Set()\n }\n // lazy only store 2 items - this is not the case in V1.6.0 anymore\n // we need to check the first parameter is string or not\n if (args.length > 2) {\n if (Array.isArray(args[0])) { // lazy store\n // check if this type of this event already register in the lazy store\n let [,,t] = args;\n if (!this.checkTypeInLazyStore(evt, t)) {\n fnSet.add(args)\n }\n } else {\n if (!this.checkContentExist(args, fnSet)) {\n this.logger('(addToStore)', `insert new`, args)\n fnSet.add(args)\n }\n }\n } else { // add straight to lazy store\n fnSet.add(args)\n }\n store.set(evt, fnSet)\n return [store, fnSet.size]\n }\n\n /**\n * @param {array} args for compare\n * @param {object} fnSet A Set to search from\n * @return {boolean} true on exist\n */\n checkContentExist(args, fnSet) {\n let list = Array.from(fnSet)\n return !!list.filter(l => {\n let [hash,] = l;\n if (hash === args[0]) {\n return true;\n }\n return false;\n }).length;\n }\n\n /**\n * get the existing type to make sure no mix type add to the same store\n * @param {string} evtName event name\n * @param {string} type the type to check\n * @return {boolean} true you can add, false then you can't add this type\n */\n checkTypeInStore(evtName, type) {\n this.validateEvt(evtName, type)\n let all = this.$get(evtName, true)\n if (all === false) {\n // pristine it means you can add\n return true;\n }\n // it should only have ONE type in ONE event store\n return !all.filter(list => {\n let [ ,,,t ] = list;\n return type !== t;\n }).length;\n }\n\n /**\n * This is checking just the lazy store because the structure is different\n * therefore we need to use a new method to check it\n */\n checkTypeInLazyStore(evtName, type) {\n this.validateEvt(evtName, type)\n let store = this.lazyStore.get(evtName)\n this.logger('(checkTypeInLazyStore)', store)\n if (store) {\n return !!Array\n .from(store)\n .filter(l => {\n let [,,t] = l;\n return t !== type;\n }).length\n }\n return false;\n }\n\n /**\n * wrapper to re-use the addToStore,\n * V1.3.0 add extra check to see if this type can add to this evt\n * @param {string} evt event name\n * @param {string} type on or once\n * @param {function} callback function\n * @param {object} context the context the function execute in or null\n * @return {number} size of the store\n */\n addToNormalStore(evt, type, callback, context = null) {\n this.logger('(addToNormalStore)', evt, type, 'try to add to normal store')\n // @TODO we need to check the existing store for the type first!\n if (this.checkTypeInStore(evt, type)) {\n this.logger('(addToNormalStore)', `${type} can add to ${evt} normal store`)\n let key = this.hashFnToKey(callback)\n let args = [this.normalStore, evt, key, callback, context, type]\n let [_store, size] = Reflect.apply(this.addToStore, this, args)\n this.normalStore = _store;\n return size;\n }\n return false;\n }\n\n /**\n * Add to lazy store this get calls when the callback is not register yet\n * so we only get a payload object or even nothing\n * @param {string} evt event name\n * @param {array} payload of arguments or empty if there is none\n * @param {object} [context=null] the context the callback execute in\n * @param {string} [type=false] register a type so no other type can add to this evt\n * @return {number} size of the store\n */\n addToLazyStore(evt, payload = [], context = null, type = false) {\n // this is add in V1.6.0\n // when there is type then we will need to check if this already added in lazy store\n // and no other type can add to this lazy store\n let args = [this.lazyStore, evt, this.toArray(payload), context]\n if (type) {\n args.push(type)\n }\n let [_store, size] = Reflect.apply(this.addToStore, this, args)\n this.lazyStore = _store;\n return size;\n }\n\n /**\n * make sure we store the argument correctly\n * @param {*} arg could be array\n * @return {array} make sured\n */\n toArray(arg) {\n return Array.isArray(arg) ? arg : [arg];\n }\n\n /**\n * setter to store the Set in private\n * @param {object} obj a Set\n */\n set normalStore(obj) {\n NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj)\n }\n\n /**\n * @return {object} Set object\n */\n get normalStore() {\n return NB_EVENT_SERVICE_PRIVATE_STORE.get(this)\n }\n\n /**\n * setter to store the Set in lazy store\n * @param {object} obj a Set\n */\n set lazyStore(obj) {\n NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj)\n }\n\n /**\n * @return {object} the lazy store Set\n */\n get lazyStore() {\n return NB_EVENT_SERVICE_PRIVATE_LAZY.get(this)\n }\n\n /**\n * generate a hashKey to identify the function call\n * The build-in store some how could store the same values!\n * @param {function} fn the converted to string function\n * @return {string} hashKey\n */\n hashFnToKey(fn) {\n return hashCode2Str(fn.toString())\n }\n}\n","// The top level\nimport NbStoreService from './store-service'\n// export\nexport default class EventService extends NbStoreService {\n /**\n * class constructor\n */\n constructor(config = {}) {\n super(config)\n }\n\n /**\n * logger function for overwrite\n */\n logger() {}\n\n //////////////////////////\n // PUBLIC METHODS //\n //////////////////////////\n\n /**\n * Register your evt handler, note we don't check the type here,\n * we expect you to be sensible and know what you are doing.\n * @param {string} evt name of event\n * @param {function} callback bind method --> if it's array or not\n * @param {object} [context=null] to execute this call in\n * @return {number} the size of the store\n */\n $on(evt , callback , context = null) {\n const type = 'on';\n this.validate(evt, callback)\n // first need to check if this evt is in lazy store\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register first then call later\n if (lazyStoreContent === false) {\n this.logger('($on)', `${evt} callback is not in lazy store`)\n // @TODO we need to check if there was other listener to this\n // event and are they the same type then we could solve that\n // register the different type to the same event name\n\n return this.addToNormalStore(evt, type, callback, context)\n }\n this.logger('($on)', `${evt} found in lazy store`)\n // this is when they call $trigger before register this callback\n let size = 0;\n lazyStoreContent.forEach(content => {\n let [ payload, ctx, t ] = content;\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.logger(`($on)`, `call run on ${evt}`)\n this.run(callback, payload, context || ctx)\n size += this.addToNormalStore(evt, type, callback, context || ctx)\n })\n return size;\n }\n\n /**\n * once only registered it once, there is no overwrite option here\n * @NOTE change in v1.3.0 $once can add multiple listeners\n * but once the event fired, it will remove this event (see $only)\n * @param {string} evt name\n * @param {function} callback to execute\n * @param {object} [context=null] the handler execute in\n * @return {boolean} result\n */\n $once(evt , callback , context = null) {\n this.validate(evt, callback)\n const type = 'once';\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register before call $trigger\n let nStore = this.normalStore;\n if (lazyStoreContent === false) {\n this.logger('($once)', `${evt} not in the lazy store`)\n // v1.3.0 $once now allow to add multiple listeners\n return this.addToNormalStore(evt, type, callback, context)\n } else {\n // now this is the tricky bit\n // there is a potential bug here that cause by the developer\n // if they call $trigger first, the lazy won't know it's a once call\n // so if in the middle they register any call with the same evt name\n // then this $once call will be fucked - add this to the documentation\n this.logger('($once)', lazyStoreContent)\n const list = Array.from(lazyStoreContent)\n // should never have more than 1\n const [ payload, ctx, t ] = list[0]\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.logger('($once)', `call run for ${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 store`)\n added = this.addToNormalStore(evt, type, callback, context)\n }\n if (lazyStoreContent !== false) {\n // there are data store in lazy store\n this.logger('($only)', `${evt} found data in lazy store to execute`)\n const list = Array.from(lazyStoreContent)\n // $only allow to trigger this multiple time on the single handler\n list.forEach( l => {\n const [ payload, ctx, t ] = l;\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.logger(`($only)`, `call run for ${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 store`)\n added = this.addToNormalStore(evt, type, callback, context)\n }\n if (lazyStoreContent !== false) {\n // there are data store in lazy store\n this.logger('($onlyOnce)', lazyStoreContent)\n const list = Array.from(lazyStoreContent)\n // should never have more than 1\n const [ payload, ctx, t ] = list[0]\n if (t && t !== 'onlyOnce') {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.logger(`($onlyOnce)`, `call run for ${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 // @1.8.0 to add the suspend queue\n let added = this.$queue(evt, payload, context, type)\n this.logger('($trigger)', evt, 'found; add to queue: ', added)\n if (added === true) {\n this.logger('($trigger)', evt, 'not 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 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 this.validateEvt(evt)\n let stores = [ this.lazyStore, this.normalStore ]\n let found = false;\n stores.forEach(store => {\n if (store.has(evt)) {\n found = true;\n this.logger('($off)', evt)\n store.delete(evt)\n }\n })\n return found;\n }\n\n /**\n * return all the listener from the event\n * @param {string} evtName event name\n * @param {boolean} [full=false] if true then return the entire content\n * @return {array|boolean} listerner(s) or false when not found\n */\n $get(evt, full = false) {\n this.validateEvt(evt)\n let store = this.normalStore;\n if (store.has(evt)) {\n return Array\n .from(store.get(evt))\n .map( l => {\n if (full) {\n return l;\n }\n let [key, callback, ] = l;\n return callback;\n })\n }\n return false;\n }\n\n /**\n * store the return result from the run\n * @param {*} value whatever return from callback\n */\n set $done(value) {\n this.logger('($done)', 'value: ', value)\n if (this.keep) {\n this.result.push(value)\n } else {\n this.result = value;\n }\n }\n\n /**\n * @TODO is there any real use with the keep prop?\n * getter for $done\n * @return {*} whatever last store result\n */\n get $done() {\n if (this.keep) {\n this.logger('(get $done)', this.result)\n return this.result[this.result.length - 1]\n }\n return this.result;\n }\n\n\n}\n","// default\nimport NBEventService from './src/event-service'\n\nexport default NBEventService\n","// this will generate a event emitter and will be use everywhere\nimport NBEventService from 'nb-event-service'\n// create a clone version so we know which one we actually is using\nexport default class JsonqlWsEvt extends NBEventService {\n\n constructor(logger) {\n if (typeof logger !== 'function') {\n throw new Error(`Just die here the logger is not a function!`)\n }\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","// mapping the resolver to their respective nsp\nimport { JSONQL_PATH, NSP_SET, PUBLIC_NAMESPACE } from 'jsonql-constants'\nimport { groupByNamespace, extractSocketPart } from 'jsonql-utils/module'\nimport { JsonqlResolverNotFoundError } from 'jsonql-errors'\n\nimport { MISSING_PROP_ERR } from '../options/constants'\n\n/**\n * Just make sure the object contain what we are looking for\n * @param {object} opts configuration from checkOptions\n * @return {object} the target content\n */\nconst getResolverList = contract => {\n const result = extractSocketPart(contract)\n if (result !== false) {\n return result\n }\n throw new JsonqlResolverNotFoundError(MISSING_PROP_ERR)\n}\n\n/**\n * process the contract first\n * @param {object} opts configuration\n * @return {object} sorted list\n */\nexport default function processContract(opts) {\n const { contract, enableAuth } = opts\n if (enableAuth) {\n return groupByNamespace(contract)\n }\n return {\n [NSP_SET]: { [JSONQL_PATH]: getResolverList(contract) },\n [PUBLIC_NAMESPACE]: JSONQL_PATH\n }\n}\n","// group all the small functions here\nimport { JS_WS_SOCKET_IO_NAME, JS_WS_NAME, EMIT_REPLY_TYPE } from 'jsonql-constants'\nimport { toArray, createEvt } from 'jsonql-utils/src/generic'\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\n// we shouldn't do this anymore\nexport const fixWss = (url, serverType) => {\n // ws only allow ws:// path\n if (serverType === JS_WS_NAME) {\n return url.replace('http://', 'ws://')\n }\n return url\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 * @param {object} nsps namespace as key\n * @param {string} type of server\n */\nexport const disconnect = (nsps, type = JS_WS_SOCKET_IO_NAME) => {\n try {\n // @TODO need to figure out a better way here?\n const method = type === JS_WS_SOCKET_IO_NAME ? 'disconnect' : 'terminate';\n for (let namespace in nsps) {\n let nsp = nsps[namespace]\n if (nsp && nsp[method]) {\n Reflect.apply(nsp[method], null, [])\n }\n }\n } catch(e) {\n // socket.io throw a this.destroy of undefined?\n console.error('Disconnect call failed', e)\n }\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_PROP_NAME, RESULT_PROP_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 {boolean} useCallbackStyle use on or not\n * @param {array} args arguments\n * @return {void} nothing\n */\nexport function actionCall(ee, namespace, resolverName, useCallbackStyle, args = []) {\n const eventName = createEvt(namespace, EMIT_REPLY_TYPE)\n const RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME\n // debugFn(`actionCall: ${eventName} --> ${resolverName}`, args)\n ee.$trigger(eventName, [resolverName, toArray(args)])\n // once we trigger there is nothing return from the resolve\n // @TODO if we need the next then call to have the result back\n // then we need to listen to the event callback here as well\n return new Promise((resolver, rejecter) => {\n ee.$on(\n createEvt(namespace, resolverName, RESULT_SUBFIX),\n function actionCallResultHandler(result) {\n // debugFn(`got the first result`, result)\n respondHandler(result, resolver, rejecter)\n }\n )\n })\n}\n","// @TODO using the obj.on syntax to do the same thing\n/*\nThe new callback style `useCallbackStyle` set to true then use this one\nclient.resolverName.on(EVENT_NAME, cb)\n*/\nimport { JsonqlValidationError, JsonqlError, finalCatch } from 'jsonql-errors'\nimport {\n ERROR_TYPE,\n DATA_KEY,\n ERROR_KEY,\n ERROR_PROP_NAME,\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME,\n READY_PROP_NAME,\n ON_ERROR_PROP_NAME,\n ON_RESULT_PROP_NAME,\n ON_MESSAGE_PROP_NAME\n} from 'jsonql-constants'\nimport { CB_FN_NAME } from '../options/constants'\n\nimport { respondHandler } from './respond-handler'\nimport { chainFns, injectToFn, createEvt, toArray, isFunc, isString } from '../utils'\n\n/**\n * Add extra property to the resolver via the getter\n * @param {function} fn the resolver itself\n * @param {object} ee event emitter\n * @param {string} namespace the namespace this belongs to\n * @param {string} resolverName resolver namee\n * @param {object} params from the contract\n * @return {array} same as what goes in\n */\nexport function setupCallbackApi(fn, ee, namespace, resolverName, params) {\n return [\n injectToFn(fn, CB_FN_NAME, function(evtName, callback) {\n if (isString(evtName) && isFunc(callback)) {\n switch(evtName) {\n case RESULT_PROP_NAME:\n ee.$on(\n createEvt(namespace, resolverName, ON_RESULT_PROP_NAME),\n function resultHandler(result) {\n respondHandler(result, callback, (error) => {\n ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error)\n })\n }\n )\n break;\n // register the handler for this message event\n case MESSAGE_PROP_NAME:\n ee.$only(\n createEvt(namespace, resolverName, ON_MESSAGE_PROP_NAME),\n function onMessageCallback(args) {\n respondHandler(args, callback, (error) => {\n ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error)\n })\n }\n )\n break;\n case READY_PROP_NAME:\n ee.$only(\n createEvt(namespace, resolverName, ON_ERROR_PROP_NAME),\n callback\n )\n break;\n default:\n ee.$trigger(\n createEvt(namespace, resolverName, ON_ERROR_PROP_NAME),\n new JsonqlError(resolverName, `Unknown event name ${evtName}!`)\n )\n }\n }\n }),\n ee,\n namespace,\n resolverName,\n params\n ]\n}\n","// break up the original setup resolver method here\nimport { JsonqlValidationError, finalCatch } from 'jsonql-errors'\nimport {\n ERROR_TYPE,\n DATA_KEY,\n ERROR_KEY,\n ON_ERROR_PROP_NAME,\n ON_MESSAGE_PROP_NAME,\n ON_RESULT_PROP_NAME\n} from 'jsonql-constants'\nimport { MY_NAMESPACE } from '../options/constants'\nimport { chainFns, objDefineProps, injectToFn, createEvt, toArray, isFunc } from '../utils'\n\nimport { respondHandler } from './respond-handler'\nimport { setupSend } from './setup-send'\nimport { setupCallbackApi } from './setup-callback-api'\n\n/**\n * The first one in the chain\n * @return {array}\n */\nconst setupNamespace = (fn, ee, namespace, resolverName, params, useCallbackStyle) => [\n injectToFn(fn, MY_NAMESPACE, namespace),\n ee,\n namespace,\n resolverName,\n params,\n useCallbackStyle\n]\n\n// onResult handler\nconst setupOnResult = (fn, ee, namespace, resolverName, params, useCallbackStyle) => [\n objDefineProps(fn, ON_RESULT_PROP_NAME, function(resultCallback) {\n if (isFunc(resultCallback)) {\n ee.$on(\n createEvt(namespace, resolverName, ON_RESULT_PROP_NAME),\n function resultHandler(result) {\n respondHandler(result, resultCallback, (error) => {\n ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error)\n })\n }\n )\n }\n }),\n ee,\n namespace,\n resolverName,\n params,\n useCallbackStyle\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\nconst setupOnMessage = (fn, ee, namespace, resolverName, params, useCallbackStyle) => [\n objDefineProps(fn, ON_MESSAGE_PROP_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 ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error)\n })\n }\n // register the handler for this message event\n ee.$only(createEvt(namespace, resolverName, ON_MESSAGE_PROP_NAME), onMessageCallback)\n }\n }),\n ee,\n namespace,\n resolverName,\n params,\n useCallbackStyle\n]\n\n// add an ON_ERROR_PROP_NAME handler\nconst setupOnError = (fn, ee, namespace, resolverName, params, useCallbackStyle) => [\n objDefineProps(fn, ON_ERROR_PROP_NAME, function(resolverErrorHandler) {\n if (isFunc(resolverErrorHandler)) {\n // please note ON_ERROR_PROP_NAME can add multiple listners\n ee.$only(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), resolverErrorHandler)\n }\n }),\n ee,\n namespace,\n resolverName,\n params,\n useCallbackStyle\n]\n\n/**\n * Add extra property to the resolver\n * @param {string} namespace where this belongs\n * @param {string} resolverName name as event name\n * @param {object} params from contract\n * @param {function} fn resolver function\n * @param {object} ee EventEmitter\n * @param {boolean} useCallbackStyle new callback style\n * @return {function} resolver\n */\nexport function setupResolver(namespace, resolverName, params, fn, ee, useCallbackStyle) {\n // also need to setup a getter to get back the namespace of this resolver\n let args = [setupNamespace]\n useCallbackStyle ? args.push(setupCallbackApi) : args.push(setupOnResult, setupOnMessage, setupOnError)\n args.push(setupSend)\n // get the executor\n const executor = Reflect.apply(chainFns, null, args)\n\n return Reflect.apply(executor, null, [fn, ee, namespace, resolverName, params, useCallbackStyle])\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 { JsonqlError, JsonqlValidationError, finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport {\n ERROR_PROP_NAME,\n LOGIN_PROP_NAME,\n READY_PROP_NAME,\n ON_ERROR_PROP_NAME,\n ON_LOGIN_PROP_NAME,\n ON_READY_PROP_NAME\n} from 'jsonql-constants'\nimport { actionCall } from './action-call'\nimport {\n createEvt,\n toArray,\n injectToFn,\n objDefineProps,\n chainFns,\n isString,\n isFunc,\n isObjectHasKey\n} from '../utils'\nimport { CB_FN_NAME } from '../options/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 {boolean} useCallbackStyle on style or not\n * @return {function} resolver\n */\nexport function createResolver(ee, namespace, resolverName, params, useCallbackStyle) {\n // note we pass the new withResult=true option\n return function(...args) {\n return validateAsync(args, params.params, true)\n .then(_args => actionCall(ee, namespace, resolverName, useCallbackStyle, _args))\n .catch(finalCatch)\n }\n}\n\n/**\n * The problem is the namespace can have more than one\n * and we only have on onError message\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @param {object} nspSet namespace keys\n * @param {boolean} useCallbackStyle use cb or not\n * @return {object} obj with onError prop\n */\nexport function createNamespaceErrorHandler(obj, ee, nspSet) {\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the obj itself\n return objDefineProps(obj, ON_ERROR_PROP_NAME, function namespaceErrorCallbackHandler(namespaceErrorHandler) {\n if (isFunc(namespaceErrorHandler)) {\n // please note ON_ERROR_PROP_NAME can add multiple listners\n for (let namespace in nspSet) {\n // this one is very tricky, we need to make sure the trigger is calling\n // with the namespace as well as the error\n ee.$on(createEvt(namespace, ON_ERROR_PROP_NAME), namespaceErrorHandler)\n }\n }\n })\n}\n\n/**\n * This event will fire when the socket.io.on('connection') and ws.onopen\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @param {object} nspSet namespace keys\n * @return {object} obj with onReady prop\n */\nexport function createOnReadyhandler(obj, ee, nspSet) {\n return objDefineProps(obj, ON_READY_PROP_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_PROP_NAME, onReadyCallback)\n }\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 * @param {object} opts configuration\n * @return {object} obj with onLogin prop\n */\nexport function createOnLoginhandler(obj, ee, opts) {\n if (opts.enableAuth) {\n return objDefineProps(obj, ON_LOGIN_PROP_NAME, function onLoginCallbackHandler(onLoginCallback) {\n if (isFunc(onLoginCallback)) {\n // only one callback can registered with it, TBC\n ee.$only(ON_LOGIN_PROP_NAME, onLoginCallback)\n }\n })\n }\n // just skip it\n return obj\n}\n\n/**\n * when useCallbackStyle=true use this instead of the above method\n * @param {object} obj the base object to attach to\n * @param {object} ee EventEmitter\n * @param {object} nspSet the map\n * @param {object} opts configuration\n * @return {object} obj\n */\nexport function createCallbackHandler(obj, ee, nspSet, opts) {\n return injectToFn(obj, CB_FN_NAME, function onHandler(evtName, callback) {\n if (isString(evtName) && isFunc(callback)) {\n switch (evtName) {\n case ERROR_PROP_NAME:\n for (let namespace in nspSet) {\n // this one is very tricky, we need to make sure the trigger is calling\n // with the namespace as well as the error\n ee.$on(createEvt(namespace, ERROR_PROP_NAME), callback)\n }\n break;\n case LOGIN_PROP_NAME: // @TODO should only available when enableAuth=true\n ee.$only(LOGIN_PROP_NAME, callback)\n break;\n case READY_PROP_NAME:\n ee.$on(READY_PROP_NAME, callback)\n break;\n default:\n ee.$trigger(ERROR_PROP_NAME, new JsonqlError(CB_FN_NAME, `Unknown event name ${evtName}!`))\n }\n }\n // @TODO need to issue another error here!\n })\n}\n","// take out from the resolver-methods\nimport { LOGIN_EVENT_NAME, LOGOUT_EVENT_NAME } from 'jsonql-constants'\nimport { JsonqlValidationError } from 'jsonql-errors'\nimport { injectToFn, chainFns, isString } from '../utils'\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 * break out from createAuthMethods to allow chaining call\n * @param {object} obj the main client object\n * @param {object} ee event emitter\n * @param {object} opts configuration\n * @return {array} modified input\n */\nconst setupLoginHandler = (obj, ee, opts) => [\n injectToFn(obj, opts.loginHandlerName, function loginHandler(token) {\n if (token && isString(token)) {\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 ee,\n opts\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} ee event emitter\n * @param {object} opts configuration\n * @return {object} the modified obj\n */\nconst setupLogoutHandler = (obj, ee, opts) => (\n injectToFn(obj, opts.logoutHandlerName, function logoutHandler(...args) {\n ee.$trigger(LOGOUT_EVENT_NAME, args)\n })\n)\n\n/**\n * Create auth related methods\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @param {object} opts configuration\n * @return {object} obj with auth methods if any\n */\nexport function createAuthMethods(obj, ee, opts) {\n if (opts.enableAuth) {\n return chainFns(setupLoginHandler, setupLogoutHandler)(obj, ee, opts)\n }\n return obj\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 { setupResolver } from './setup-resolver'\nimport {\n createResolver,\n createNamespaceErrorHandler,\n createOnReadyhandler,\n createOnLoginhandler,\n createCallbackHandler\n} from './resolver-methods'\nimport { createAuthMethods } from './setup-auth-methods'\nimport { injectToFn, chainProcessPromises } from '../utils'\n\n/**\n * step one get the obj map with the namespace\n * @param {object} opts configuration\n * @param {object} nspMap resolvers index by their namespace\n * @param {object} ee EventEmitter\n * @return {promise} resolve the obj mapped, and start the chain\n */\nfunction getMappedObj(opts, nspMap, ee) {\n let obj = {};\n // let resolverNames = [];\n const { nspSet } = nspMap;\n const { useCallbackStyle } = opts; // @1.2.1\n for (let namespace in nspSet) {\n let list = nspSet[namespace]\n for (let resolverName in list) {\n // resolverNames.push(resolverName)\n let params = list[resolverName]\n let fn = createResolver(ee, namespace, resolverName, params, useCallbackStyle)\n // this should set as a getter therefore can not be overwrite by accident\n // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n obj = injectToFn(obj, resolverName, setupResolver(namespace, resolverName, params, fn, ee, useCallbackStyle))\n }\n }\n // move this two method down to helpers\n // we want these methods visible in debug or console.log\n obj.devHelpers = {\n // this is a helper method for the developer to know the namespace inside\n getNsp: () => Object.keys(nspSet),\n // simple get version trick\n getVer: () => opts.version || 'NOT SET'\n // not really necessary because the dev can query the contract\n // getResolverNames: () => resolverNames\n }\n // resolve the obj to start the chain\n // chain the result to allow the chain processing\n return Promise.resolve(obj)\n}\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 generator(opts, nspMap, ee) {\n const { nspSet } = nspMap\n const { useCallbackStyle, enableAuth } = opts;\n let args = [getMappedObj]\n if (useCallbackStyle) {\n args.push(obj => createCallbackHandler(obj, ee, nspSet, opts))\n } else {\n args.push(\n obj1 => createNamespaceErrorHandler(obj1, ee, nspSet),\n obj2 => createOnReadyhandler(obj2, ee, nspSet),\n )\n if (enableAuth) {\n args.push(obj3 => createOnLoginhandler(obj3, ee, opts))\n }\n }\n // this only apply to when enableAuth = true\n if (enableAuth) {\n args.push(obj4 => createAuthMethods(obj4, ee, opts))\n }\n // run it\n const executor = Reflect.apply(chainProcessPromises, null, args)\n return executor(opts, nspMap, ee)\n}\n","// create options\nimport { checkConfigAsync } from 'jsonql-params-validator'\nimport { wsCoreDefaultOptions, wsCoreConstProps } from './defaults'\nimport { fixWss, getHostName } from '../utils'\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 checkOptionsWrapper(config, defaultOptions, constProps) {\n const wsConstProps = Object.assign(wsCoreConstProps, constProps)\n const defaultCheckOptions = Object.assign(wsCoreDefaultOptions, defaultOptions)\n /*\n const fn = postConfigCheck(checkMap, constProps, checkConfig)\n return fn(config)\n */\n return checkConfigAsync(config, defaultCheckOptions, 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 postWsOptions(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 // debug('CONFIGURATION OPTIONS', opts)\n return opts\n })\n}\n\n/**\n * check the configuration\n * @param {object} config user supplied configuration\n * @param {object} defaultOptions the check map\n * @param {object} constProps developer supplied configuration\n * @return {object} after checked\n */\nfunction checkWsCoreOptions(config, defaultOptions, constProps) {\n return checkOptionsWrapper(config, defaultOptions, constProps)\n .then(postWsOptions)\n}\n\n\nexport {\n wsCoreDefaultOptions,\n wsCoreConstProps,\n checkWsCoreOptions,\n postWsOptions\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 { checkWsCoreOptions } from './options'\nimport { ee, processContract } from './utils'\nimport { CHECKED_KEY } from 'jsonql-constants'\n\n/**\n * @TODO remove this implmenetation once the test is done\n */\nconst dummyLogger = (...args) => {\n Reflect.apply(console.info, console, ['[jsonql-ws-client-core]', ...args])\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 log('CHECKED_KEY', opts[CHECKED_KEY])\n if (eventEmitter) {\n log(`eventEmitter is:`, eventEmitter.name)\n return eventEmitter\n }\n log(`Create a new Event Emitter`)\n return new ee( opts.log )\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 opts.log = dummyLogger\n }\n opts.log('--- wsClientCore config opts ---', opts)\n return opts\n}\n\n/**\n * 0.5.0 we break up the wsClientCore in two parts one without the config check \n * @param {function} socketClientResolver \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(socketClientResolver, config) {\n return Promise.resolve(config)\n .then(getLogFn)\n .then(opts => ({\n opts,\n nspMap: processContract(opts),\n ee: getEventEmitter(opts)\n }))\n .then(\n ({opts, nspMap, ee}) => socketClientResolver(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} socketClientResolver this is the one method export by various clients\n * @param {object} [defaultOptions={}] 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 {object} the wsClient instance with all the available API\n */\nexport function wsClientCore(socketClientResolver, defaultOptions = {}, constProps = {}) {\n // we need to inject property to this client later\n // therefore we need to do it this way\n return (config = {}) => (\n checkWsCoreOptions(config, defaultOptions, constProps)\n .then(opts => wsClientCoreAction(socketClientResolver, opts))\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\nconst wsClientAppProps = {}\n\nexport { wsClientAppProps, wsClientConstProps }\n","// pass the different type of ws to generate the client\nimport { TOKEN_PARAM_NAME } from 'jsonql-constants'\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 */\nconst 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 * The bug was in the wsOptions where ws doesn'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 */\nexport function createWsClient(WebSocket, auth = false) {\n if (auth === false) {\n return function createWsClientHandler(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 createWsAuthClientHandler(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","// since both the ws and io version are\n// pre-defined in the client-generator\n// and this one will have the same parameters\n// and the callback is identical\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 } = opts;\n const url = namespace ? [hostname, namespace].join('/') : wssPath;\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 } = opts;\n const url = namespace ? [hostname, namespace].join('/') : wssPath;\n if (token && typeof token !== 'string') {\n throw new Error(`Expect token to be string, but got ${token}`)\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_PROP_NAME, ERROR_PROP_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 * @param {object} opts configuration\n * @return {void}\n */\nexport function triggerNamespacesOnError(ee, namespaces, message, opts = {}) {\n const { useCallbackStyle } = opts;\n const ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME;\n namespaces.forEach( namespace => {\n ee.$call(createEvt(namespace, ERROR_SUBFIX), [{ message, namespace }])\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\nimport {\n ERROR_PROP_NAME,\n RESULT_PROP_NAME,\n // LOGIN_EVENT_NAME,\n LOGOUT_EVENT_NAME,\n NOT_LOGIN_ERR_MSG,\n ON_ERROR_PROP_NAME,\n ON_RESULT_PROP_NAME,\n // ON_MESSAGE_PROP_NAME,\n} from 'jsonql-constants'\nimport { EMIT_EVT, SOCKET_IO, WS } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A fake ee handler\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 { useCallbackStyle, log } = opts;\n const ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME;\n const RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME;\n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n\n log('[notLoginHandler] hijack the ws call', namespace, resolverName, args)\n\n let error = {\n message: NOT_LOGIN_ERR_MSG\n }\n // It should just throw error here and should not call the result\n // because that's channel for handling normal event not the fake one\n ee.$call(createEvt(namespace, resolverName, ERROR_SUBFIX), [error])\n // also trigger the result handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, RESULT_SUBFIX), [{ 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 * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {array} namespaces namespace(s)\n * @param {object} ee Event Emitter instance\n * @param {function} bindWsHandler binding the ee to ws --> this is the core bit\n * @param {array} namespaces array of namespace available\n * @param {object} nsps namespaced nsp\n * @return {void} nothing\n */\nexport function clientEventHandler(opts, nspMap, ee, bindWsHandler, namespaces, nsps) {\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 const { log } = opts;\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run a waterfall here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace;\n if (nsps[namespace]) {\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n if (opts.serverType === SOCKET_IO) {\n let { nspSet } = nspMap;\n args.push(nspSet[namespace])\n }\n Reflect.apply(bindWsHandler, null, args)\n } else {\n // a dummy placeholder\n notLoginWsHandler(namespace, ee, opts)\n }\n })\n // this will be available regardless enableAuth\n // because the server can log the client out\n ee.$on(LOGOUT_EVENT_NAME, function logoutEvtHandler() {\n log('LOGOUT_EVENT_NAME')\n // disconnect(nsps, opts.serverType)\n // we need to issue error to all the namespace onError handler\n triggerNamespacesOnError(ee, namespaces, LOGOUT_EVENT_NAME)\n // rebind all of the handler to the fake one\n namespaces.forEach( namespace => {\n clearMainEmitEvt(ee, namespace)\n // clear out the nsp\n nsps[namespace] = false;\n // add a NOT LOGIN error if call\n notLoginWsHandler(namespace, ee, opts)\n })\n })\n}\n","// take the ws reply data for use\nimport { WS_EVT_NAME, WS_DATA_NAME, WS_REPLY_TYPE } from 'jsonql-constants'\nimport { isString } from 'jsonql-params-validator'\nimport { isObjectHasKey } from 'jsonql-utils/module'\nimport { JsonqlError, clientErrorsHandler } from 'jsonql-errors'\n\nconst keys = [ WS_REPLY_TYPE, WS_EVT_NAME, WS_DATA_NAME ]\n\n/**\n * @param {object} payload should be string when reply but could be transformed\n * @return {boolean} true is OK\n */\nconst isWsReply = payload => {\n const { data } = payload\n if (data) {\n let result = keys.filter(key => isObjectHasKey(data, key))\n return (result.length === keys.length) ? data : false\n }\n return false\n}\n\n/**\n * @param {object} payload This is the entire ws Event Object\n * @return {object} false on failed\n */\nconst extractWsPayload = payload => {\n const { data } = payload;\n let json = isString(data) ? JSON.parse(data) : data\n let fdata;\n if ((fdata = isWsReply(json)) !== false) {\n return {\n resolverName: fdata[WS_EVT_NAME],\n data: fdata[WS_DATA_NAME],\n type: fdata[WS_REPLY_TYPE]\n }\n }\n throw new JsonqlError('payload can not be decoded', payload)\n}\n// export it\nexport default extractWsPayload\n","// the WebSocket main handler\nimport {\n LOGIN_EVENT_NAME,\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_TYPE,\n\n ON_ERROR_PROP_NAME,\n ON_MESSAGE_PROP_NAME,\n ON_RESULT_PROP_NAME,\n ON_READY_PROP_NAME,\n ON_LOGIN_PROP_NAME,\n\n ERROR_PROP_NAME,\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME,\n READY_PROP_NAME,\n LOGIN_PROP_NAME\n} from 'jsonql-constants'\nimport { createQueryStr, createEvt } from 'jsonql-utils/module'\nimport extractWsPayload from './extract-ws-payload'\n\n\n/**\n * under extremely circumstances we might not even have a resolverName, then\n * we issue a global error for the developer to catch it\n * @param {object} ee event emitter\n * @param {string} namespace nsp\n * @param {string} resolverName resolver\n * @param {object} json decoded payload or error object\n * @param {string} ERROR_EVT_NAME the error event name\n * @return {undefined} nothing return\n */\nconst errorTypeHandler = (ee, namespace, resolverName, json, ERROR_EVT_NAME) => {\n let evt = [namespace]\n if (resolverName) {\n evt.push(resolverName)\n }\n evt.push(ERROR_EVT_NAME)\n let evtName = Reflect.apply(createEvt, null, evt)\n // test if there is a data field\n let payload = json.data || json;\n ee.$trigger(evtName, [payload])\n}\n\n/**\n * Binding the even to socket normally\n * @param {string} namespace\n * @param {object} ws the nsp\n * @param {object} ee EventEmitter\n * @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 wsMainHandler(namespace, ws, ee, isPrivate, opts) {\n const { useCallbackStyle, log } = opts;\n\n log(`wsMainHandler log test`)\n\n const READY_EVT_NAME = useCallbackStyle ? READY_PROP_NAME : ON_READY_PROP_NAME;\n const LOGIN_EVT_NAME = useCallbackStyle ? LOGIN_PROP_NAME : ON_LOGIN_PROP_NAME;\n const MESSAGE_EVT_NAME = useCallbackStyle ? MESSAGE_PROP_NAME : ON_MESSAGE_PROP_NAME;\n const RESULT_EVT_NAME = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME;\n const ERROR_EVT_NAME = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME;\n // connection open\n ws.onopen = function onOpenCallback() {\n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(READY_EVT_NAME, namespace)\n // need an extra parameter here to id the private nsp\n if (isPrivate) {\n log(`isPrivate and fire the ${LOGIN_EVT_NAME}`)\n ee.$call(LOGIN_EVT_NAME, namespace)\n }\n // add listener only after the open is called\n ee.$only(\n createEvt(namespace, EMIT_REPLY_TYPE),\n function wsMainOnEvtHandler(resolverName, args) {\n log('calling server', resolverName, args)\n ws.send(\n createQueryStr(resolverName, args)\n )\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 const json = extractWsPayload(payload)\n const { resolverName, type } = json;\n log('Hear from server', type, json)\n switch (type) {\n case EMIT_REPLY_TYPE:\n let e1 = createEvt(namespace, resolverName, MESSAGE_EVT_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, RESULT_EVT_NAME)\n let x = ee.$trigger(e2, [json])\n // log(`ACKNOWLEDGE_REPLY_TYPE`, e2, json)\n break;\n case ERROR_TYPE:\n // this is handled error and we won't throw it\n // we need to extract the error from json\n log(`ERROR_TYPE`)\n errorTypeHandler(ee, namespace, resolverName, json, ERROR_EVT_NAME)\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, ERROR_EVT_NAME)\n // let error = {error: {'message': 'Unhandled event!', type}};\n // ee.$trigger(createEvt(namespace, resolverName, ON_RESULT_PROP_NAME), [error])\n }\n } catch(e) {\n console.error(`ws.onmessage error`, e)\n errorTypeHandler(ee, namespace, false, e, ERROR_EVT_NAME)\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 // listen to the LOGOUT_EVENT_NAME\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","// actually binding the event client to the socket client\nimport { getNameFromPayload, getNamespaceInOrder } from 'jsonql-utils/module'\nimport { LOGIN_EVENT_NAME, LOGOUT_EVENT_NAME, JS_WS_NAME } from 'jsonql-constants'\nimport {\n createNspClient,\n createNspAuthClient,\n clientEventHandler,\n // comment them out for now they are not in use\n // triggerNamespacesOnError,\n // disconnect\n clearMainEmitEvt\n} from 'jsonql-ws-client-core/share'\nimport { wsMainHandler } from './ws-main-handler'\n\n/**\n * Because the nsps can be throw away so it doesn't matter the scope\n * this will get reuse again\n * @param {object} opts configuration\n * @param {object} nspMap from contract\n * @param {string|null} token whether we have the token at run time\n * @return {object} nsps namespace with namespace as key\n */\nconst createNsps = function(opts, nspMap, token) {\n let { nspSet, publicNamespace } = nspMap\n let login = false\n let namespaces = []\n let nsps = {}\n // first we need to binding all the events handler\n if (opts.enableAuth) { // && opts.useJwt\n login = true; // just saying we need to listen to login event\n namespaces = getNamespaceInOrder(nspSet, publicNamespace)\n nsps = namespaces.map((namespace, i) => {\n if (i === 0) {\n if (token) {\n opts.token = token\n // console.log('create createNspAuthClient at run time', opts)\n return {[namespace]: createNspAuthClient(namespace, opts)}\n }\n return {[namespace]: false}\n }\n return {[namespace]: createNspClient(namespace, opts)}\n }).reduce((first, next) => Object.assign(first, next), {})\n } else {\n let namespace = getNameFromPayload(nspSet)\n namespaces.push(namespace)\n // standard without login\n // the stock version should not have a namespace\n nsps[namespace] = createNspClient(false, opts)\n }\n // return\n return { nsps, namespaces, login }\n}\n\n/**\n * create a ws client\n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nexport function createClient(opts, nspMap, ee) {\n // arguments that don't change\n const args = [opts, nspMap, ee, wsMainHandler]\n // now create the nsps\n const { token, log } = opts\n const { nsps, namespaces, login } = createNsps(opts, nspMap, token)\n // binding the listeners - and it will listen to LOGOUT event\n // to unbind itself, and the above call will bind it again\n Reflect.apply(clientEventHandler, null, args.concat([namespaces, nsps]))\n // setup listener\n if (login) {\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandler(tokenLater) {\n\n log('createClient LOGIN_EVENT_NAME')\n\n // debugFn(`LOGIN_EVENT_NAME called with token:`, tokenLater)\n // @BUG 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\n // disconnect(nsps, JS_WS_NAME)\n\n // @TODO should we trigger error on this one?\n // triggerNamespacesOnError(ee, namespaces, LOGIN_EVENT_NAME)\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNsps(opts, nspMap, tokenLater)\n // rebind it\n Reflect.apply(\n clientEventHandler,\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\n }\n // return what input\n return { opts, nspMap, ee }\n}\n","// share method to create the wsClientResolver\n\nimport { createWsClient } from './create-ws-client'\nimport { createClient } from './create-client'\n\n/**\n * combine the create client resolver\n * @param {object} ws the different WebSocket module\n * @return {function} the wsClientResolver\n */\nexport default function createClientResolver(ws) {\n const client = createWsClient(ws)\n const authClient = createWsClient(ws, true)\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(opts, nspMap, ee) {\n opts.nspClient = client;\n opts.nspAuthClient = authClient;\n // @1.0.7 remove later once everything fixed \n const { log } = opts;\n if (log && typeof log === 'function') {\n log('@jsonql/ws ee', ee.name)\n log('@jsonql/ws createClientResolver', opts)\n }\n // console.log(`contract`, opts.contract)\n return createClient(opts, nspMap, ee)\n }\n}\n","// 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 createClientResolver from './core/create-client-resolver'\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 createClientResolver(WebSocket)\n","// this is the module entry point for node\nimport { wsClientCore } from 'jsonql-ws-client-core'\nimport { wsClientAppProps, wsClientConstProps } from './options'\nimport wsClientResolver from './node-ws-client-resolver'\n\n// export back the function and that's it\nexport default function wsBrowserClient(config = {}, constProps = {}) {\n const initMethod = wsClientCore(wsClientResolver, wsClientAppProps, Object.assign(wsClientConstProps, constProps))\n return initMethod(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;;;;;;;;;;;;;"} \ No newline at end of file diff --git a/packages/@jsonql/ws/package.json b/packages/@jsonql/ws/package.json index 7b17a58b..1d6740e2 100644 --- a/packages/@jsonql/ws/package.json +++ b/packages/@jsonql/ws/package.json @@ -19,13 +19,16 @@ "prepare": "npm run build", "build:cjs": "TARGET=cjs rollup -c", "build:umd": "TARGET=umd rollup -c", - "build:test": "npm run build:cjs && npm run build:umd", + "build:cjs:module": "TARGET=cjs-module rollup -c", + "build:umd:module": "TARGET=umd-module rollup -c", + "build:test": "npm run build:cjs && npm run build:umd && npm run build:cjs:module && npm run build:umd:module", "build": "NODE_ENV=production npm run build:cjs && NODE_ENV=production npm run build:umd", "test:browser:basic": "npm run build:umd && DEBUG=jsonql-ws-client*,server-io-core* node ./tests/browser/run-qunit.js", "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-client* ava ./tests/ws-client-basic.test.js", "test:auth": "npm run build:cjs && DEBUG=jsonql-ws-client*,-jsonql-ws-client:nb-event-service ava ./tests/ws-client-auth.test.js", + "test:auth:debug": "JSONQL_DEBUG=0 DEBUG=jsonql-ws-client* ava ./tests/ws-client-auth.test.js", "test:login": "npm run build:cjs && DEBUG=jsonql-ws*,-jsonql-ws-client:nb-event-service ava ./tests/ws-client-auth-login.test.js", "test:chain": "npm run build:cjs && DEBUG=jsonql-ws-client*,-jsonql-ws-client:nb-event-service ava ./tests/ws-client-chain.test.js" }, diff --git a/packages/@jsonql/ws/tests/log/auth-test-fail.log b/packages/@jsonql/ws/tests/log/auth-test-fail.log new file mode 100644 index 00000000..adff522c --- /dev/null +++ b/packages/@jsonql/ws/tests/log/auth-test-fail.log @@ -0,0 +1,60 @@ +⠙ 2020-03-03T10:49:33.277Z jsonql-ws-client:test:ws-auth [call bindWsHandler] true jsonql/private +⠹ 2020-03-03T10:49:33.277Z jsonql-ws-client:test:ws-auth wsMainHandler log test +⠸ 2020-03-03T10:49:33.278Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:49:33.278Z jsonql-ws-client:test:ws-auth ($on) __logout__ callback is not in lazy store +2020-03-03T10:49:33.278Z jsonql-ws-client:test:ws-auth (addToNormalStore) __logout__ on try to add to normal store +⠼ 2020-03-03T10:49:33.278Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to __logout__ normal store +⠴ 2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for __logout__ +⠦ 2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1943629321', [Function: closeEvtHandler], null, 'on' ] +2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth [call bindWsHandler] false jsonql/public +2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth wsMainHandler log test +2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth ($on) __logout__ callback is not in lazy store +2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth (addToNormalStore) __logout__ on try to add to normal store +⠧ 2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to __logout__ normal store +2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth (addToStore) __logout__ existed +2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth ($on) __logout__ callback is not in lazy store +2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth (addToNormalStore) __logout__ on try to add to normal store +2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to __logout__ normal store +⠇ 2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth (addToStore) __logout__ existed +2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '2054930596', [Function: logoutEvtHandler], null, 'on' ] +2020-03-03T10:49:33.279Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +⠏ 2020-03-03T10:49:33.280Z jsonql-ws-client:test:ws-auth ($only) __login__ add to store +2020-03-03T10:49:33.280Z jsonql-ws-client:test:ws-auth (addToNormalStore) __login__ only try to add to normal store +2020-03-03T10:49:33.280Z jsonql-ws-client:test:ws-auth (addToNormalStore) only can add to __login__ normal store +2020-03-03T10:49:33.280Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for __login__ +2020-03-03T10:49:33.280Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1338112777', [Function: loginEventHandler], null, 'only' ] +⠋ 2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +⠙ 2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth ($on) onReady callback is not in lazy store +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (addToNormalStore) onReady on try to add to normal store +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to onReady normal store +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for onReady +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1603363042', [Function: onReadyCallback], null, 'on' ] +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth ($on) onReady callback is not in lazy store +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (addToNormalStore) onReady on try to add to normal store +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to onReady normal store +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (addToStore) onReady existed +⠹ 2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth ($only) onLogin add to store +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (addToNormalStore) onLogin only try to add to normal store +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (addToNormalStore) only can add to onLogin normal store +2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for onLogin +⠸ 2020-03-03T10:49:33.282Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '689744962', [Function: onLoginCallback], null, 'only' ] +⠼ 2020-03-03T10:49:33.300Z jsonql-ws-client:test:ws-auth ws.onopen listened +⠴ 2020-03-03T10:49:33.300Z jsonql-ws-client:test:ws-auth isPrivate and fire the onLogin +2020-03-03T10:49:33.300Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:49:33.300Z jsonql-ws-client:test:ws-auth ($only) jsonql/private_emit add to store +2020-03-03T10:49:33.300Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/private_emit only try to add to normal store +2020-03-03T10:49:33.300Z jsonql-ws-client:test:ws-auth (addToNormalStore) only can add to jsonql/private_emit normal store +⠦ 2020-03-03T10:49:33.300Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for jsonql/private_emit +2020-03-03T10:49:33.300Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1066061919', [Function: wsMainOnEvtHandler], null, 'only' ] +⠧ 2020-03-03T10:49:33.300Z jsonql-ws-client:test:ws-auth ws.onopen listened +⠇ 2020-03-03T10:49:33.300Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:49:33.300Z jsonql-ws-client:test:ws-auth ($only) jsonql/public_emit add to store +2020-03-03T10:49:33.300Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/public_emit only try to add to normal store +⠏ 2020-03-03T10:49:33.301Z jsonql-ws-client:test:ws-auth (addToNormalStore) only can add to jsonql/public_emit normal store +2020-03-03T10:49:33.301Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for jsonql/public_emit +⠋ 2020-03-03T10:49:33.301Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1066061919', [Function: wsMainOnEvtHandler], null, 'only' ] diff --git a/packages/@jsonql/ws/tests/log/auth-test.log b/packages/@jsonql/ws/tests/log/auth-test.log new file mode 100644 index 00000000..c63b9e6b --- /dev/null +++ b/packages/@jsonql/ws/tests/log/auth-test.log @@ -0,0 +1,466 @@ +⠏ 2020-03-03T10:46:29.815Z jsonql-ws-client:test:ws-auth [call bindWsHandler] true jsonql/private +⠋ 2020-03-03T10:46:29.815Z jsonql-ws-client:test:ws-auth wsMainHandler log test +⠙ 2020-03-03T10:46:29.816Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +⠹ 2020-03-03T10:46:29.816Z jsonql-ws-client:test:ws-auth ($on) __logout__ callback is not in lazy store +2020-03-03T10:46:29.816Z jsonql-ws-client:test:ws-auth (addToNormalStore) __logout__ on try to add to normal store +⠸ 2020-03-03T10:46:29.817Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to __logout__ normal store +⠼ 2020-03-03T10:46:29.817Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for __logout__ +⠴ 2020-03-03T10:46:29.817Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '921130464', [Function], null, 'on' ] +⠦ 2020-03-03T10:46:29.818Z jsonql-ws-client:test:ws-auth [call bindWsHandler] false jsonql/public +⠧ 2020-03-03T10:46:29.818Z jsonql-ws-client:test:ws-auth wsMainHandler log test +⠇ 2020-03-03T10:46:29.818Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +⠏ 2020-03-03T10:46:29.818Z jsonql-ws-client:test:ws-auth ($on) __logout__ callback is not in lazy store +2020-03-03T10:46:29.818Z jsonql-ws-client:test:ws-auth (addToNormalStore) __logout__ on try to add to normal store +⠋ 2020-03-03T10:46:29.818Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to __logout__ normal store +⠙ 2020-03-03T10:46:29.818Z jsonql-ws-client:test:ws-auth (addToStore) __logout__ existed +⠹ 2020-03-03T10:46:29.819Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +⠸ 2020-03-03T10:46:29.819Z jsonql-ws-client:test:ws-auth ($on) __logout__ callback is not in lazy store +2020-03-03T10:46:29.819Z jsonql-ws-client:test:ws-auth (addToNormalStore) __logout__ on try to add to normal store +⠼ 2020-03-03T10:46:29.819Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to __logout__ normal store +⠴ 2020-03-03T10:46:29.819Z jsonql-ws-client:test:ws-auth (addToStore) __logout__ existed +⠦ 2020-03-03T10:46:29.819Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1238311657', [Function], null, 'on' ] +⠧ 2020-03-03T10:46:29.820Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +⠇ 2020-03-03T10:46:29.820Z jsonql-ws-client:test:ws-auth ($only) __login__ add to store +⠏ 2020-03-03T10:46:29.820Z jsonql-ws-client:test:ws-auth (addToNormalStore) __login__ only try to add to normal store +2020-03-03T10:46:29.820Z jsonql-ws-client:test:ws-auth (addToNormalStore) only can add to __login__ normal store +⠋ 2020-03-03T10:46:29.820Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for __login__ +⠙ 2020-03-03T10:46:29.820Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '-77217986', [Function], null, 'only' ] +⠸ 2020-03-03T10:46:29.826Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +⠼ 2020-03-03T10:46:29.826Z jsonql-ws-client:test:ws-auth ($on) onReady callback is not in lazy store +2020-03-03T10:46:29.826Z jsonql-ws-client:test:ws-auth (addToNormalStore) onReady on try to add to normal store +2020-03-03T10:46:29.826Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to onReady normal store +⠴ 2020-03-03T10:46:29.826Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for onReady +2020-03-03T10:46:29.826Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1603363042', [Function: onReadyCallback], null, 'on' ] +2020-03-03T10:46:29.827Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:46:29.827Z jsonql-ws-client:test:ws-auth ($on) onReady callback is not in lazy store +2020-03-03T10:46:29.827Z jsonql-ws-client:test:ws-auth (addToNormalStore) onReady on try to add to normal store +2020-03-03T10:46:29.827Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to onReady normal store +2020-03-03T10:46:29.827Z jsonql-ws-client:test:ws-auth (addToStore) onReady existed +⠦ 2020-03-03T10:46:29.827Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] +2020-03-03T10:46:29.827Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:46:29.827Z jsonql-ws-client:test:ws-auth ($only) onLogin add to store +2020-03-03T10:46:29.827Z jsonql-ws-client:test:ws-auth (addToNormalStore) onLogin only try to add to normal store +2020-03-03T10:46:29.827Z jsonql-ws-client:test:ws-auth (addToNormalStore) only can add to onLogin normal store +2020-03-03T10:46:29.827Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for onLogin +⠧ 2020-03-03T10:46:29.827Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '689744962', [Function: onLoginCallback], null, 'only' ] +⠇ 2020-03-03T10:46:29.838Z jsonql-ws-client:test:ws-auth ws.onopen listened +⠏ 2020-03-03T10:46:29.839Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] } } +⠋ 2020-03-03T10:46:29.839Z jsonql-ws-client:test:ws-auth ($trigger) onReady found; add to queue: null +2020-03-03T10:46:29.839Z jsonql-ws-client:test:ws-auth ($trigger) call run for onReady +2020-03-03T10:46:29.839Z jsonql-ws-client:test:ws-auth (run) function onReadyCallback(w) { + debug('onReady -->', w) + t.pass() + } jsonql/private null +2020-03-03T10:46:29.839Z jsonql-ws-client:test:ws-auth onReady --> jsonql/private +⠙ 2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth ($done) value: undefined +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth ($trigger) call run for onReady +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth (run) function onReadyAgainCallback(w) { + debug('onReady again', w) + t.pass() + } jsonql/private null +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth onReady again jsonql/private +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth ($done) value: undefined +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth isPrivate and fire the onLogin +⠹ 2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] } } +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth ($trigger) onLogin found; add to queue: null +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth ($trigger) call run for onLogin +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth (run) function onLoginCallback(n) { + debug(`onLogin -->`, n) + t.pass() + t.end() + } jsonql/private null +⠸ 2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth onLogin --> jsonql/private +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth ($done) value: undefined +⠼ 2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth ($only) jsonql/private_emit add to store +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/private_emit only try to add to normal store +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth (addToNormalStore) only can add to jsonql/private_emit normal store +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for jsonql/private_emit +2020-03-03T10:46:29.840Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1702879906', [Function], null, 'only' ] +⠦ Should able to handle multiple onMessage and one onLogin callback + + 1 passed2020-03-03T10:46:29.841Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:46:29.841Z jsonql-ws-client:test:ws-auth ($on) jsonql/public_pinging_onResult callback is not in lazy store +2020-03-03T10:46:29.841Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/public_pinging_onResult on try to add to normal store +2020-03-03T10:46:29.841Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to jsonql/public_pinging_onResult normal store +2020-03-03T10:46:29.841Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for jsonql/public_pinging_onResult +2020-03-03T10:46:29.841Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1204663069', [Function], null, 'on' ] +2020-03-03T10:46:29.841Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:46:29.842Z jsonql-ws-client:test:ws-auth ($only) jsonql/public_pinging_onMessage add to store +2020-03-03T10:46:29.842Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/public_pinging_onMessage only try to add to normal store +2020-03-03T10:46:29.842Z jsonql-ws-client:test:ws-auth (addToNormalStore) only can add to jsonql/public_pinging_onMessage normal store +2020-03-03T10:46:29.842Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for jsonql/public_pinging_onMessage +2020-03-03T10:46:29.842Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1204663069', [Function], null, 'only' ] +2020-03-03T10:46:29.842Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] }, + 'jsonql/private_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/public_pinging_onResult' => Set { [ '1204663069', [Function], null, 'on' ] }, + 'jsonql/public_pinging_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] } } +2020-03-03T10:46:29.842Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for jsonql/public_emit +2020-03-03T10:46:29.842Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map { 'jsonql/public_emit' => Set { [ [Array], null ] } } +2020-03-03T10:46:29.842Z jsonql-ws-client:test:ws-auth ($on) jsonql/public_pinging_onResult callback is not in lazy store +2020-03-03T10:46:29.842Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/public_pinging_onResult on try to add to normal store +2020-03-03T10:46:29.842Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to jsonql/public_pinging_onResult normal store +⠧ Should able to handle multiple onMessage and one onLogin callback + + 1 passed2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth ws.onopen listened +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] }, + 'jsonql/private_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/public_pinging_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/public_pinging_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] } } +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth ($trigger) onReady found; add to queue: null +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth ($trigger) call run for onReady +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth (run) function onReadyCallback(w) { + debug('onReady -->', w) + t.pass() + } jsonql/public null +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth onReady --> jsonql/public +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth ($done) value: undefined +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth ($trigger) call run for onReady +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth (run) function onReadyAgainCallback(w) { + debug('onReady again', w) + t.pass() + } jsonql/public null +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth onReady again jsonql/public +⠇ Should able to handle multiple onMessage and one onLogin callback + + 1 passed2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth (takeFromStore) has jsonql/public_emit Set { [ [ 'pinging', [Array] ], null ] } +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth ($only) jsonql/public_emit add to store +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/public_emit only try to add to normal store +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth (addToNormalStore) only can add to jsonql/public_emit normal store +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for jsonql/public_emit +2020-03-03T10:46:29.843Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1702879906', [Function], null, 'only' ] +2020-03-03T10:46:29.844Z jsonql-ws-client:test:ws-auth ($only) jsonql/public_emit found data in lazy store to execute +2020-03-03T10:46:29.844Z jsonql-ws-client:test:ws-auth ($only) call run for jsonql/public_emit +⠏ Should able to handle multiple onMessage and one onLogin callback +⠋ Should able to handle multiple onMessage and one onLogin callback + + 1 passed2020-03-03T10:46:29.850Z jsonql-ws-client:test:ws-auth Hear from server acknowledge { resolverName: 'pinging', +⠙ Should able to handle multiple onMessage and one onLogin callback + + 1 passed2020-03-03T10:46:29.851Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] }, + 'jsonql/private_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/public_pinging_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/public_pinging_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] }, + 'jsonql/public_emit' => Set { [ '1702879906', [Function], null, 'only' ] } } +2020-03-03T10:46:29.851Z jsonql-ws-client:test:ws-auth ($trigger) jsonql/public_pinging_onResult found; add to queue: null +2020-03-03T10:46:29.851Z jsonql-ws-client:test:ws-auth ($trigger) call run for jsonql/public_pinging_onResult +2020-03-03T10:46:29.851Z jsonql-ws-client:test:ws-auth (run) function(o){respondHandler(o,e,(function(e){r.$trigger(createEvt(t,n,ON_ERROR_PROP_NAME),e)}))} [ { resolverName: 'pinging', + data: 'connection established', +⠹ Should able to handle multiple onMessage and one onLogin callback + + 1 passed2020-03-03T10:46:29.851Z jsonql-ws-client:test:ws-auth ($done) value: undefined +2020-03-03T10:46:29.851Z jsonql-ws-client:test:ws-auth ($trigger) call run for jsonql/public_pinging_onResult +2020-03-03T10:46:29.852Z jsonql-ws-client:test:ws-auth (run) function(e){respondHandler(e,n,o)} [ { resolverName: 'pinging', + data: 'connection established', + type: 'acknowledge' } ] null +2020-03-03T10:46:29.852Z jsonql-ws-client:test:ws-auth ($done) value: undefined +2020-03-03T10:46:29.852Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] }, + 'jsonql/private_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/public_pinging_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/public_pinging_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] }, + 'jsonql/public_emit' => Set { [ '1702879906', [Function], null, 'only' ] } } +⠸ Should able to handle multiple onMessage and one onLogin callback + + 1 passed2020-03-03T10:46:29.852Z jsonql-ws-client:test:ws-auth (run) function(e,t){i("calling server",e,t),r.send(createQueryStr(e,t))} [ 'pinging', [ 'ping' ] ] null +2020-03-03T10:46:29.852Z jsonql-ws-client:test:ws-auth calling server pinging [ 'ping' ] +2020-03-03T10:46:29.852Z jsonql-ws-client:test:ws-auth ($done) value: undefined +2020-03-03T10:46:29.852Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:46:29.852Z jsonql-ws-client:test:ws-auth ($on) jsonql/public_pinging_onResult callback is not in lazy store +2020-03-03T10:46:29.852Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/public_pinging_onResult on try to add to normal store +⠼ Should able to handle multiple onMessage and one onLogin callback +⠴ Should able to handle multiple onMessage and one onLogin callback + + 1 passed2020-03-03T10:46:29.853Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] }, + 'jsonql/private_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/public_pinging_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/public_pinging_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] }, + 'jsonql/public_emit' => Set { [ '1702879906', [Function], null, 'only' ] } } +2020-03-03T10:46:29.853Z jsonql-ws-client:test:ws-auth ($trigger) jsonql/public_pinging_onMessage found; add to queue: null +2020-03-03T10:46:29.853Z jsonql-ws-client:test:ws-auth ($trigger) call run for jsonql/public_pinging_onMessage +⠦ Should able to handle multiple onMessage and one onLogin callback + + 1 passed2020-03-03T10:46:29.853Z jsonql-ws-client:test:ws-auth ($done) value: undefined +⠧ Should able to handle multiple onMessage and one onLogin callback + + 1 passed2020-03-03T10:46:29.854Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] }, + 'jsonql/private_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/public_pinging_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, +⠇ Should able to handle multiple onMessage and one onLogin callback + + 1 passed2020-03-03T10:46:29.855Z jsonql-ws-client:test:ws-auth ($trigger) jsonql/public_pinging_onMessage found; add to queue: null +2020-03-03T10:46:29.855Z jsonql-ws-client:test:ws-auth ($trigger) call run for jsonql/public_pinging_onMessage +2020-03-03T10:46:29.855Z jsonql-ws-client:test:ws-auth (run) function(o){respondHandler(o,e,(function(e){r.$trigger(createEvt(t,n,ON_ERROR_PROP_NAME),e)}))} [ { resolverName: 'pinging', data: 'ping', type: 'emit' } ] null +2020-03-03T10:46:29.855Z jsonql-ws-client:test:ws-auth ($done) value: undefined +2020-03-03T10:46:29.855Z jsonql-ws-client:test:ws-auth EMIT_REPLY_TYPE jsonql/public_pinging_onMessage 1 +2020-03-03T10:46:29.855Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] }, + 'jsonql/private_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/public_pinging_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/public_pinging_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] }, + 'jsonql/public_emit' => Set { [ '1702879906', [Function], null, 'only' ] } } +2020-03-03T10:46:29.855Z jsonql-ws-client:test:ws-auth ($trigger) jsonql/public_emit found; add to queue: null +2020-03-03T10:46:29.855Z jsonql-ws-client:test:ws-auth ($trigger) call run for jsonql/public_emit +⠏ Should able to handle multiple onMessage and one onLogin callback + + 1 passed2020-03-03T10:46:29.856Z jsonql-ws-client:test:ws-auth ($done) value: undefined +2020-03-03T10:46:29.856Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:46:29.856Z jsonql-ws-client:test:ws-auth ($on) jsonql/public_pinging_onResult callback is not in lazy store +2020-03-03T10:46:29.856Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/public_pinging_onResult on try to add to normal store +2020-03-03T10:46:29.856Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to jsonql/public_pinging_onResult normal store +2020-03-03T10:46:29.856Z jsonql-ws-client:test:ws-auth (addToStore) jsonql/public_pinging_onResult existed +2020-03-03T10:46:29.856Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] }, + 'jsonql/private_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/public_pinging_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/public_pinging_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] }, + 'jsonql/public_emit' => Set { [ '1702879906', [Function], null, 'only' ] } } +2020-03-03T10:46:29.856Z jsonql-ws-client:test:ws-auth ($trigger) jsonql/public_emit found; add to queue: null +2020-03-03T10:46:29.856Z jsonql-ws-client:test:ws-auth ($trigger) call run for jsonql/public_emit +⠋ Should able to handle multiple onMessage and one onLogin callback + + 1 passed2020-03-03T10:46:29.856Z jsonql-ws-client:test:ws-auth ($done) value: undefined +2020-03-03T10:46:29.856Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:46:29.856Z jsonql-ws-client:test:ws-auth ($on) jsonql/public_pinging_onResult callback is not in lazy store +2020-03-03T10:46:29.856Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/public_pinging_onResult on try to add to normal store +⠹ It should able to connect to the WebSocket public namespace + + 2 passed2020-03-03T10:46:29.857Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:46:29.857Z jsonql-ws-client:test:ws-auth ($on) jsonql/private_sendExtraMsg_onResult callback is not in lazy store +2020-03-03T10:46:29.857Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/private_sendExtraMsg_onResult on try to add to normal store +2020-03-03T10:46:29.857Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to jsonql/private_sendExtraMsg_onResult normal store +2020-03-03T10:46:29.857Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for jsonql/private_sendExtraMsg_onResult +2020-03-03T10:46:29.857Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1204663069', [Function], null, 'on' ] +2020-03-03T10:46:29.857Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:46:29.857Z jsonql-ws-client:test:ws-auth ($only) jsonql/private_sendExtraMsg_onMessage add to store +2020-03-03T10:46:29.857Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/private_sendExtraMsg_onMessage only try to add to normal store +2020-03-03T10:46:29.857Z jsonql-ws-client:test:ws-auth (addToNormalStore) only can add to jsonql/private_sendExtraMsg_onMessage normal store +2020-03-03T10:46:29.857Z jsonql-ws-client:test:ws-auth (addToStore) create new Set for jsonql/private_sendExtraMsg_onMessage +2020-03-03T10:46:29.857Z jsonql-ws-client:test:ws-auth (addToStore) insert new [ '1204663069', [Function], null, 'only' ] +2020-03-03T10:46:29.857Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] }, + 'jsonql/private_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/public_pinging_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/public_pinging_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] }, + 'jsonql/public_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/private_sendExtraMsg_onResult' => Set { [ '1204663069', [Function], null, 'on' ] }, + 'jsonql/private_sendExtraMsg_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] } } +2020-03-03T10:46:29.858Z jsonql-ws-client:test:ws-auth ($trigger) jsonql/private_emit found; add to queue: null +2020-03-03T10:46:29.858Z jsonql-ws-client:test:ws-auth ($trigger) call run for jsonql/private_emit +2020-03-03T10:46:29.858Z jsonql-ws-client:test:ws-auth (run) function(e,t){i("calling server",e,t),r.send(createQueryStr(e,t))} [ 'sendExtraMsg', [ 100 ] ] null +2020-03-03T10:46:29.858Z jsonql-ws-client:test:ws-auth calling server sendExtraMsg [ 100 ] +⠸ It should able to connect to the WebSocket public namespace + + 2 passed2020-03-03T10:46:29.858Z jsonql-ws-client:test:ws-auth ($on) jsonql/private_sendExtraMsg_onResult callback is not in lazy store +2020-03-03T10:46:29.858Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/private_sendExtraMsg_onResult on try to add to normal store +2020-03-03T10:46:29.858Z jsonql-ws-client:test:ws-auth (addToNormalStore) on can add to jsonql/private_sendExtraMsg_onResult normal store +⠼ It should able to connect to the WebSocket public namespace +⠴ It should able to connect to the WebSocket public namespace + + 2 passed2020-03-03T10:46:29.860Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] }, + 'jsonql/private_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/public_pinging_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/public_pinging_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] }, + 'jsonql/public_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/private_sendExtraMsg_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/private_sendExtraMsg_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] } } +2020-03-03T10:46:29.860Z jsonql-ws-client:test:ws-auth ($trigger) jsonql/public_pinging_onMessage found; add to queue: null +2020-03-03T10:46:29.860Z jsonql-ws-client:test:ws-auth ($trigger) call run for jsonql/public_pinging_onMessage +⠦ It should able to connect to the WebSocket public namespace + + 2 passed2020-03-03T10:46:29.861Z jsonql-ws-client:test:ws-auth ($done) value: undefined +2020-03-03T10:46:29.861Z jsonql-ws-client:test:ws-auth EMIT_REPLY_TYPE jsonql/public_pinging_onMessage 1 +2020-03-03T10:46:29.861Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] }, + 'jsonql/private_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/public_pinging_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/public_pinging_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] }, + 'jsonql/public_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/private_sendExtraMsg_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/private_sendExtraMsg_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] } } +2020-03-03T10:46:29.861Z jsonql-ws-client:test:ws-auth ($trigger) jsonql/public_emit found; add to queue: null +⠧ It should able to connect to the WebSocket public namespace + + 2 passed2020-03-03T10:46:29.861Z jsonql-ws-client:test:ws-auth calling server pinging [ 'giving up' ] +2020-03-03T10:46:29.861Z jsonql-ws-client:test:ws-auth ($done) value: undefined +2020-03-03T10:46:29.861Z jsonql-ws-client:test:ws-auth (takeFromStore) lazyStore Map {} +2020-03-03T10:46:29.861Z jsonql-ws-client:test:ws-auth ($on) jsonql/public_pinging_onResult callback is not in lazy store +2020-03-03T10:46:29.861Z jsonql-ws-client:test:ws-auth (addToNormalStore) jsonql/public_pinging_onResult on try to add to normal store +⠇ It should able to connect to the WebSocket public namespace + + 2 passed2020-03-03T10:46:29.861Z jsonql-ws-client:test:ws-auth Hear from server emit { resolverName: 'sendExtraMsg', data: 102, type: 'emit' } +2020-03-03T10:46:29.862Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] }, + 'jsonql/private_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/public_pinging_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/public_pinging_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] }, + 'jsonql/public_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/private_sendExtraMsg_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/private_sendExtraMsg_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] } } +⠏ It should able to connect to the WebSocket public namespace + + 2 passed2020-03-03T10:46:29.862Z jsonql-ws-client:test:ws-auth (run) function(o){respondHandler(o,e,(function(e){r.$trigger(createEvt(t,n,ON_ERROR_PROP_NAME),e)}))} [ { resolverName: 'sendExtraMsg', data: 102, type: 'emit' } ] null +2020-03-03T10:46:29.862Z jsonql-ws-client:test:ws-auth ($done) value: undefined +⠋ It should able to connect to the WebSocket public namespace + + 2 passed2020-03-03T10:46:29.862Z jsonql-ws-client:test:ws-auth ($trigger) normalStore Map { + '__logout__' => Set { + [ '921130464', [Function], null, 'on' ], + [ '1238311657', [Function], null, 'on' ] }, + '__login__' => Set { [ '-77217986', [Function], null, 'only' ] }, + 'onReady' => Set { + [ '1603363042', [Function: onReadyCallback], null, 'on' ], + [ '1233278316', [Function: onReadyAgainCallback], null, 'on' ] }, + 'onLogin' => Set { [ '689744962', [Function: onLoginCallback], null, 'only' ] }, + 'jsonql/private_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/public_pinging_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/public_pinging_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] }, + 'jsonql/public_emit' => Set { [ '1702879906', [Function], null, 'only' ] }, + 'jsonql/private_sendExtraMsg_onResult' => Set { + [ '1204663069', [Function], null, 'on' ], + [ '479026866', [Function], null, 'on' ] }, + 'jsonql/private_sendExtraMsg_onMessage' => Set { [ '1204663069', [Function], null, 'only' ] } } +2020-03-03T10:46:29.862Z jsonql-ws-client:test:ws-auth ($trigger) jsonql/private_sendExtraMsg_onResult found; add to queue: null +2020-03-03T10:46:29.862Z jsonql-ws-client:test:ws-auth ($trigger) call run for jsonql/private_sendExtraMsg_onResult +⠙ It should able to connect to the WebSocket public namespace + + 2 passed2020-03-03T10:46:29.863Z jsonql-ws-client:test:ws-auth ($done) value: undefined +⠹ It should able to connect to the WebSocket public namespace + + 3 tests passed diff --git a/packages/@jsonql/ws/tests/ws-client-auth.test.js b/packages/@jsonql/ws/tests/ws-client-auth.test.js index 4837e9e9..9efd28b8 100644 --- a/packages/@jsonql/ws/tests/ws-client-auth.test.js +++ b/packages/@jsonql/ws/tests/ws-client-auth.test.js @@ -1,7 +1,9 @@ // standard ws client test without auth const test = require('ava') -const wsClient = require('../main') +const modulePath = process.env.JSONQL_DEBUG ? '../node-org' : '../main' +const wsClient = require(modulePath) + const serverSetup = require('./fixtures/server-setup') const { join } = require('path') diff --git a/packages/ws-client-core/src/core/action-call.js b/packages/ws-client-core/src/core/action-call.js index bf95aa36..c5af4eb1 100644 --- a/packages/ws-client-core/src/core/action-call.js +++ b/packages/ws-client-core/src/core/action-call.js @@ -8,23 +8,29 @@ import { respondHandler } from './respond-handler' * @param {object} ee EventEmitter * @param {string} namespace where this belongs * @param {string} resolverName resolver - * @param {boolean} useCallbackStyle use on or not * @param {array} args arguments * @return {void} nothing */ -export function actionCall(ee, namespace, resolverName, useCallbackStyle, args = []) { +export function actionCall(ee, namespace, resolverName, args = []) { const eventName = createEvt(namespace, EMIT_REPLY_TYPE) - const RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME - // debugFn(`actionCall: ${eventName} --> ${resolverName}`, args) - ee.$trigger(eventName, [resolverName, toArray(args)]) + // const RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME + + debugFn(`actionCall: ${eventName} --> ${resolverName}`, args) + + ee.$trigger(eventName, [resolverName].concat(toArray(args)) + + // ee.$call(eventName) + // once we trigger there is nothing return from the resolve // @TODO if we need the next then call to have the result back // then we need to listen to the event callback here as well return new Promise((resolver, rejecter) => { ee.$on( - createEvt(namespace, resolverName, RESULT_SUBFIX), + createEvt(namespace, resolverName, ON_RESULT_PROP_NAME), function actionCallResultHandler(result) { - // debugFn(`got the first result`, result) + + debugFn(`got the first result`, result) + respondHandler(result, resolver, rejecter) } ) diff --git a/packages/ws-client-core/src/core/cb/callback-handler.js b/packages/ws-client-core/src/core/cb/callback-handler.js new file mode 100644 index 00000000..78a69af9 --- /dev/null +++ b/packages/ws-client-core/src/core/cb/callback-handler.js @@ -0,0 +1,34 @@ +// taking it out, this is kind of pointless at the moment and its potentially breaking things + +/** + * when useCallbackStyle=true use this instead of the above method + * @param {object} obj the base object to attach to + * @param {object} ee EventEmitter + * @param {object} nspSet the map + * @param {object} opts configuration + * @return {object} obj + */ +export function createCallbackHandler(obj, ee, nspSet, opts) { + return injectToFn(obj, CB_FN_NAME, function onHandler(evtName, callback) { + if (isString(evtName) && isFunc(callback)) { + switch (evtName) { + case ERROR_PROP_NAME: + for (let namespace in nspSet) { + // 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, ERROR_PROP_NAME), callback) + } + break; + case LOGIN_PROP_NAME: // @TODO should only available when enableAuth=true + ee.$only(LOGIN_PROP_NAME, callback) + break; + case READY_PROP_NAME: + ee.$on(READY_PROP_NAME, callback) + break; + default: + ee.$trigger(ERROR_PROP_NAME, new JsonqlError(CB_FN_NAME, `Unknown event name ${evtName}!`)) + } + } + // @TODO need to issue another error here! + }) +} \ No newline at end of file diff --git a/packages/ws-client-core/src/core/setup-callback-api.js b/packages/ws-client-core/src/core/cb/setup-callback-api.js similarity index 100% rename from packages/ws-client-core/src/core/setup-callback-api.js rename to packages/ws-client-core/src/core/cb/setup-callback-api.js diff --git a/packages/ws-client-core/src/core/resolver-methods.js b/packages/ws-client-core/src/core/resolver-methods.js index 66daf621..a5215e77 100644 --- a/packages/ws-client-core/src/core/resolver-methods.js +++ b/packages/ws-client-core/src/core/resolver-methods.js @@ -18,16 +18,7 @@ import { ON_READY_PROP_NAME } from 'jsonql-constants' import { actionCall } from './action-call' -import { - createEvt, - toArray, - injectToFn, - objDefineProps, - chainFns, - isString, - isFunc, - isObjectHasKey -} from '../utils' +import { createEvt, objDefineProps, isFunc } from '../utils' import { CB_FN_NAME } from '../options/constants' /** @@ -36,14 +27,13 @@ import { CB_FN_NAME } from '../options/constants' * @param {string} namespace this resolver end point * @param {string} resolverName name of resolver as event name * @param {object} params from contract - * @param {boolean} useCallbackStyle on style or not * @return {function} resolver */ -export function createResolver(ee, namespace, resolverName, params, useCallbackStyle) { +export function createResolver(ee, namespace, resolverName, params) { // note we pass the new withResult=true option return function(...args) { return validateAsync(args, params.params, true) - .then(_args => actionCall(ee, namespace, resolverName, useCallbackStyle, _args)) + .then(_args => actionCall(ee, namespace, resolverName, _args)) .catch(finalCatch) } } @@ -110,35 +100,4 @@ export function createOnLoginhandler(obj, ee, opts) { return obj } -/** - * when useCallbackStyle=true use this instead of the above method - * @param {object} obj the base object to attach to - * @param {object} ee EventEmitter - * @param {object} nspSet the map - * @param {object} opts configuration - * @return {object} obj - */ -export function createCallbackHandler(obj, ee, nspSet, opts) { - return injectToFn(obj, CB_FN_NAME, function onHandler(evtName, callback) { - if (isString(evtName) && isFunc(callback)) { - switch (evtName) { - case ERROR_PROP_NAME: - for (let namespace in nspSet) { - // 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, ERROR_PROP_NAME), callback) - } - break; - case LOGIN_PROP_NAME: // @TODO should only available when enableAuth=true - ee.$only(LOGIN_PROP_NAME, callback) - break; - case READY_PROP_NAME: - ee.$on(READY_PROP_NAME, callback) - break; - default: - ee.$trigger(ERROR_PROP_NAME, new JsonqlError(CB_FN_NAME, `Unknown event name ${evtName}!`)) - } - } - // @TODO need to issue another error here! - }) -} + -- Gitee From b3d3813d11d4c5c3a7144972126770130cbd3009 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 20:06:34 +0800 Subject: [PATCH 14/26] remove the callback options --- packages/ws-client-core/package.json | 2 +- .../src/core/cb/setup-callback-api.js | 6 ++-- packages/ws-client-core/src/core/generator.js | 31 +++++++--------- .../ws-client-core/src/core/setup-resolver.js | 35 +++++++------------ .../ws-client-core/src/core/setup-send.js | 16 ++++----- .../ws-client-core/src/options/defaults.js | 4 +-- 6 files changed, 38 insertions(+), 56 deletions(-) diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json index a7b14bf7..c29daf13 100644 --- a/packages/ws-client-core/package.json +++ b/packages/ws-client-core/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-ws-client-core", - "version": "0.5.0", + "version": "0.6.0", "description": "This is the jsonql Web Socket client core library for Node and Browser. Not for direct use.", "main": "main.js", "module": "index.js", diff --git a/packages/ws-client-core/src/core/cb/setup-callback-api.js b/packages/ws-client-core/src/core/cb/setup-callback-api.js index 4380c34b..5f9835aa 100644 --- a/packages/ws-client-core/src/core/cb/setup-callback-api.js +++ b/packages/ws-client-core/src/core/cb/setup-callback-api.js @@ -16,10 +16,10 @@ import { ON_RESULT_PROP_NAME, ON_MESSAGE_PROP_NAME } from 'jsonql-constants' -import { CB_FN_NAME } from '../options/constants' +import { CB_FN_NAME } from '../../options/constants' -import { respondHandler } from './respond-handler' -import { chainFns, injectToFn, createEvt, toArray, isFunc, isString } from '../utils' +import { respondHandler } from '../respond-handler' +import { chainFns, injectToFn, createEvt, toArray, isFunc, isString } from '../../utils' /** * Add extra property to the resolver via the getter diff --git a/packages/ws-client-core/src/core/generator.js b/packages/ws-client-core/src/core/generator.js index 969807a7..69c9d68c 100644 --- a/packages/ws-client-core/src/core/generator.js +++ b/packages/ws-client-core/src/core/generator.js @@ -6,8 +6,7 @@ import { createResolver, createNamespaceErrorHandler, createOnReadyhandler, - createOnLoginhandler, - createCallbackHandler + createOnLoginhandler } from './resolver-methods' import { createAuthMethods } from './setup-auth-methods' import { injectToFn, chainProcessPromises } from '../utils' @@ -23,16 +22,16 @@ function getMappedObj(opts, nspMap, ee) { let obj = {}; // let resolverNames = []; const { nspSet } = nspMap; - const { useCallbackStyle } = opts; // @1.2.1 + // const { useCallbackStyle } = opts; // @1.2.1 for (let namespace in nspSet) { let list = nspSet[namespace] for (let resolverName in list) { // resolverNames.push(resolverName) let params = list[resolverName] - let fn = createResolver(ee, namespace, resolverName, params, useCallbackStyle) + let fn = createResolver(ee, namespace, resolverName, params) // this should set as a getter therefore can not be overwrite by accident // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee) - obj = injectToFn(obj, resolverName, setupResolver(namespace, resolverName, params, fn, ee, useCallbackStyle)) + obj = injectToFn(obj, resolverName, setupResolver(namespace, resolverName, params, fn, ee)) } } // move this two method down to helpers @@ -60,23 +59,19 @@ function getMappedObj(opts, nspMap, ee) { */ export function generator(opts, nspMap, ee) { const { nspSet } = nspMap - const { useCallbackStyle, enableAuth } = opts; + const { enableAuth } = opts let args = [getMappedObj] - if (useCallbackStyle) { - args.push(obj => createCallbackHandler(obj, ee, nspSet, opts)) - } else { - args.push( - obj1 => createNamespaceErrorHandler(obj1, ee, nspSet), - obj2 => createOnReadyhandler(obj2, ee, nspSet), - ) - if (enableAuth) { - args.push(obj3 => createOnLoginhandler(obj3, ee, opts)) - } - } - // this only apply to when enableAuth = true + + args.push( + obj1 => createNamespaceErrorHandler(obj1, ee, nspSet), + obj2 => createOnReadyhandler(obj2, ee, nspSet), + ) + if (enableAuth) { + args.push(obj3 => createOnLoginhandler(obj3, ee, opts)) args.push(obj4 => createAuthMethods(obj4, ee, opts)) } + // run it const executor = Reflect.apply(chainProcessPromises, null, args) return executor(opts, nspMap, ee) diff --git a/packages/ws-client-core/src/core/setup-resolver.js b/packages/ws-client-core/src/core/setup-resolver.js index 66152e86..64a251ef 100644 --- a/packages/ws-client-core/src/core/setup-resolver.js +++ b/packages/ws-client-core/src/core/setup-resolver.js @@ -1,35 +1,30 @@ // break up the original setup resolver method here -import { JsonqlValidationError, finalCatch } from 'jsonql-errors' +// import { JsonqlValidationError, finalCatch } from 'jsonql-errors' import { - ERROR_TYPE, - DATA_KEY, - ERROR_KEY, ON_ERROR_PROP_NAME, ON_MESSAGE_PROP_NAME, ON_RESULT_PROP_NAME } from 'jsonql-constants' import { MY_NAMESPACE } from '../options/constants' -import { chainFns, objDefineProps, injectToFn, createEvt, toArray, isFunc } from '../utils' +import { chainFns, objDefineProps, injectToFn, createEvt, isFunc } from '../utils' import { respondHandler } from './respond-handler' import { setupSend } from './setup-send' -import { setupCallbackApi } from './setup-callback-api' /** * The first one in the chain * @return {array} */ -const setupNamespace = (fn, ee, namespace, resolverName, params, useCallbackStyle) => [ +const setupNamespace = (fn, ee, namespace, resolverName, params) => [ injectToFn(fn, MY_NAMESPACE, namespace), ee, namespace, resolverName, - params, - useCallbackStyle + params ] // onResult handler -const setupOnResult = (fn, ee, namespace, resolverName, params, useCallbackStyle) => [ +const setupOnResult = (fn, ee, namespace, resolverName, params) => [ objDefineProps(fn, ON_RESULT_PROP_NAME, function(resultCallback) { if (isFunc(resultCallback)) { ee.$on( @@ -45,13 +40,12 @@ const setupOnResult = (fn, ee, namespace, resolverName, params, useCallbackStyle ee, namespace, resolverName, - params, - useCallbackStyle + params ] // we do need to add the send prop back because it's the only way to deal with // bi-directional data stream -const setupOnMessage = (fn, ee, namespace, resolverName, params, useCallbackStyle) => [ +const setupOnMessage = (fn, ee, namespace, resolverName, params) => [ objDefineProps(fn, ON_MESSAGE_PROP_NAME, function(messageCallback) { // we expect this to be a function if (isFunc(messageCallback)) { @@ -68,12 +62,11 @@ const setupOnMessage = (fn, ee, namespace, resolverName, params, useCallbackStyl ee, namespace, resolverName, - params, - useCallbackStyle + params ] // add an ON_ERROR_PROP_NAME handler -const setupOnError = (fn, ee, namespace, resolverName, params, useCallbackStyle) => [ +const setupOnError = (fn, ee, namespace, resolverName, params) => [ objDefineProps(fn, ON_ERROR_PROP_NAME, function(resolverErrorHandler) { if (isFunc(resolverErrorHandler)) { // please note ON_ERROR_PROP_NAME can add multiple listners @@ -83,8 +76,7 @@ const setupOnError = (fn, ee, namespace, resolverName, params, useCallbackStyle) ee, namespace, resolverName, - params, - useCallbackStyle + params ] /** @@ -94,16 +86,15 @@ const setupOnError = (fn, ee, namespace, resolverName, params, useCallbackStyle) * @param {object} params from contract * @param {function} fn resolver function * @param {object} ee EventEmitter - * @param {boolean} useCallbackStyle new callback style * @return {function} resolver */ -export function setupResolver(namespace, resolverName, params, fn, ee, useCallbackStyle) { +export function setupResolver(namespace, resolverName, params, fn, ee) { // also need to setup a getter to get back the namespace of this resolver let args = [setupNamespace] - useCallbackStyle ? args.push(setupCallbackApi) : args.push(setupOnResult, setupOnMessage, setupOnError) + args.push(setupOnResult, setupOnMessage, setupOnError) args.push(setupSend) // get the executor const executor = Reflect.apply(chainFns, null, args) - return Reflect.apply(executor, null, [fn, ee, namespace, resolverName, params, useCallbackStyle]) + return Reflect.apply(executor, null, [fn, ee, namespace, resolverName, params]) } diff --git a/packages/ws-client-core/src/core/setup-send.js b/packages/ws-client-core/src/core/setup-send.js index 28c4cf76..a2ccce76 100644 --- a/packages/ws-client-core/src/core/setup-send.js +++ b/packages/ws-client-core/src/core/setup-send.js @@ -1,22 +1,18 @@ import { JsonqlValidationError, finalCatch } from 'jsonql-errors' import { - ERROR_TYPE, - DATA_KEY, ERROR_KEY, ON_ERROR_PROP_NAME, - ERROR_PROP_NAME, SEND_MSG_PROP_NAME } from 'jsonql-constants' import { validateAsync } from 'jsonql-params-validator' -import { chainFns, objDefineProps, injectToFn, createEvt, toArray, isFunc } from '../utils' +import { objDefineProps, createEvt, toArray } from '../utils' import { actionCall } from './action-call' // pairing with the server vesrion SEND_MSG_PROP_NAME // last of the chain so only return the resolver (fn) -export const setupSend = (fn, ee, namespace, resolverName, params, useCallbackStyle) => ( +export const setupSend = (fn, ee, namespace, resolverName, params) => ( objDefineProps(fn, SEND_MSG_PROP_NAME, function sendSetter(messagePayload) { - const ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME // debugFn('got payload for', messagePayload) // @NOTE change from sync interface to async @ 1.0.0 // this way we will able to catch all the error(s) @@ -26,25 +22,25 @@ export const setupSend = (fn, ee, namespace, resolverName, params, useCallbackSt if (result[ERROR_KEY] && result[ERROR_KEY].length) { // debugFn(`got ERROR_KEY`, result[ERROR_KEY]) ee.$call( - createEvt(namespace, resolverName, ERROR_SUBFIX), + createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), [new JsonqlValidationError(resolverName, result[ERROR_KEY])] ) } else { // return it just for the catch to work - if any - return actionCall(ee, namespace, resolverName, useCallbackStyle, messagePayload) + return actionCall(ee, namespace, resolverName, messagePayload) } }) .catch(err => { // debugFn(`error after validateAsync`, err) ee.$call( - createEvt(namespace, resolverName, ERROR_SUBFIX), + createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), [new JsonqlValidationError(resolverName, err)] ) }) }, function sendGetter() { // add in 1.1.4 return function sendGetterAction(...args) { return validateAsync(args, params.params, true) - .then(_args => actionCall(ee, namespace, resolverName, useCallbackStyle, _args)) + .then(_args => actionCall(ee, namespace, resolverName, _args)) .catch(finalCatch) } }) diff --git a/packages/ws-client-core/src/options/defaults.js b/packages/ws-client-core/src/options/defaults.js index 7fa909d7..b01a8041 100644 --- a/packages/ws-client-core/src/options/defaults.js +++ b/packages/ws-client-core/src/options/defaults.js @@ -14,11 +14,11 @@ import { IO_ROUNDTRIP_LOGIN, IO_HANDSHAKE_LOGIN } from 'jsonql-constants' -import { AVAILABLE_SERVERS } from './constants' +// import { AVAILABLE_SERVERS } from './constants' const AVAILABLE_METHODS = [IO_ROUNDTRIP_LOGIN, IO_HANDSHAKE_LOGIN] const wsCoreDefaultOptions = { - useCallbackStyle: createConfig(false, [BOOLEAN_TYPE]), + // useCallbackStyle: createConfig(false, [BOOLEAN_TYPE]), abandoned in 0.6.0 loginHandlerName: createConfig(ISSUER_NAME, [STRING_TYPE]), logoutHandlerName: createConfig(LOGOUT_NAME, [STRING_TYPE]), // this is for socket.io -- Gitee From 281960195f5ac5feaef7dc6c40fe3f484c9f5d8f Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 20:19:51 +0800 Subject: [PATCH 15/26] move all the utils methods out of the api.js --- packages/ws-client-core/src/api.js | 71 +++++-------------- .../ws-client-core/src/core/action-call.js | 8 +-- packages/ws-client-core/src/core/generator.js | 2 +- packages/ws-client-core/src/utils/ee.js | 20 +++++- packages/ws-client-core/src/utils/index.js | 8 ++- packages/ws-client-core/src/utils/log.js | 23 ++++++ 6 files changed, 69 insertions(+), 63 deletions(-) create mode 100644 packages/ws-client-core/src/utils/log.js diff --git a/packages/ws-client-core/src/api.js b/packages/ws-client-core/src/api.js index f177b2cf..1651bae4 100644 --- a/packages/ws-client-core/src/api.js +++ b/packages/ws-client-core/src/api.js @@ -4,45 +4,11 @@ // import { injectToFn } from 'jsonql-utils' import { generator } from './core' import { checkWsCoreOptions } from './options' -import { ee, processContract } from './utils' -import { CHECKED_KEY } from 'jsonql-constants' +import { ee, processContract, getLogFn } from './utils' + -/** - * @TODO remove this implmenetation once the test is done - */ -const dummyLogger = (...args) => { - Reflect.apply(console.info, console, ['[jsonql-ws-client-core]', ...args]) -} -/** - * getting the event emitter - * @param {object} opts configuration - * @return {object} the event emitter instance - */ -const getEventEmitter = opts => { - const { log, eventEmitter } = opts - log('CHECKED_KEY', opts[CHECKED_KEY]) - if (eventEmitter) { - log(`eventEmitter is:`, eventEmitter.name) - return eventEmitter - } - log(`Create a new Event Emitter`) - return new ee( opts.log ) -} -/** - * Make sure there is a log method - * @param {object} opts configuration - * @return {object} opts - */ -const getLogFn = opts => { - const { log } = opts // 1.3.9 if we pass a log method here then we use this - if (!log || typeof log !== 'function') { - opts.log = dummyLogger - } - opts.log('--- wsClientCore config opts ---', opts) - return opts -} /** * 0.5.0 we break up the wsClientCore in two parts one without the config check @@ -50,22 +16,23 @@ const getLogFn = opts => { * @param {object} config the already checked config */ export function wsClientCoreAction(socketClientResolver, config) { - return Promise.resolve(config) - .then(getLogFn) - .then(opts => ({ - opts, - nspMap: processContract(opts), - ee: getEventEmitter(opts) - })) - .then( - ({opts, nspMap, ee}) => socketClientResolver(opts, nspMap, ee) - ) - .then( - ({opts, nspMap, ee}) => generator(opts, nspMap, ee) - ) - .catch(err => { - console.error(`jsonql-ws-core-client init error`, err) - }) + return Promise + .resolve(config) + .then(getLogFn) + .then(opts => ({ + opts, + nspMap: processContract(opts), + ee: getEventEmitter(opts) + })) + .then( + ({opts, nspMap, ee}) => socketClientResolver(opts, nspMap, ee) + ) + .then( + ({opts, nspMap, ee}) => generator(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/core/action-call.js index c5af4eb1..30d2686c 100644 --- a/packages/ws-client-core/src/core/action-call.js +++ b/packages/ws-client-core/src/core/action-call.js @@ -16,13 +16,9 @@ export function actionCall(ee, namespace, resolverName, args = []) { // const RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME debugFn(`actionCall: ${eventName} --> ${resolverName}`, args) - - ee.$trigger(eventName, [resolverName].concat(toArray(args)) - - // ee.$call(eventName) + // this could be a problem + ee.$trigger(eventName, [resolverName, toArray(args)]) - // once we trigger there is nothing return from the resolve - // @TODO if we need the next then call to have the result back // then we need to listen to the event callback here as well return new Promise((resolver, rejecter) => { ee.$on( diff --git a/packages/ws-client-core/src/core/generator.js b/packages/ws-client-core/src/core/generator.js index 69c9d68c..9fb8c742 100644 --- a/packages/ws-client-core/src/core/generator.js +++ b/packages/ws-client-core/src/core/generator.js @@ -21,7 +21,7 @@ import { injectToFn, chainProcessPromises } from '../utils' function getMappedObj(opts, nspMap, ee) { let obj = {}; // let resolverNames = []; - const { nspSet } = nspMap; + const { nspSet } = nspMap // const { useCallbackStyle } = opts; // @1.2.1 for (let namespace in nspSet) { let list = nspSet[namespace] diff --git a/packages/ws-client-core/src/utils/ee.js b/packages/ws-client-core/src/utils/ee.js index f958f53c..06f1416c 100644 --- a/packages/ws-client-core/src/utils/ee.js +++ b/packages/ws-client-core/src/utils/ee.js @@ -1,7 +1,7 @@ // this will generate a event emitter and will be use everywhere import NBEventService from 'nb-event-service' // create a clone version so we know which one we actually is using -export default class JsonqlWsEvt extends NBEventService { +class JsonqlWsEvt extends NBEventService { constructor(logger) { if (typeof logger !== 'function') { @@ -16,3 +16,21 @@ export default class JsonqlWsEvt extends NBEventService { return'jsonql-ws-client-core' } } + +/** + * getting the event emitter + * @param {object} opts configuration + * @return {object} the event emitter instance + */ +const getEventEmitter = opts => { + const { log, eventEmitter } = opts + + if (eventEmitter) { + log(`eventEmitter is:`, eventEmitter.name) + return eventEmitter + } + log(`Create a new Event Emitter`) + return new JsonqlWsEvt( opts.log ) +} + +export { getEventEmitter } diff --git a/packages/ws-client-core/src/utils/index.js b/packages/ws-client-core/src/utils/index.js index 43eb3536..4fa59191 100644 --- a/packages/ws-client-core/src/utils/index.js +++ b/packages/ws-client-core/src/utils/index.js @@ -1,5 +1,7 @@ // export the util methods import { isArray, isString } from 'jsonql-params-validator' +import { getLogFn } from './log' +import { getEventEmitter } from './ee' // moved to jsonql-utils // some of these are unnecessary export should get rip of them import { @@ -17,8 +19,6 @@ import { postConfigCheck } from 'jsonql-utils/module' -import ee from './ee' - import processContract from './process-contract' import { fixWss, @@ -29,6 +29,9 @@ import { // export export { + getLogFn, + getEventEmitter, + isArray, isString, @@ -46,7 +49,6 @@ export { postConfigCheck, - ee, processContract, fixWss, diff --git a/packages/ws-client-core/src/utils/log.js b/packages/ws-client-core/src/utils/log.js new file mode 100644 index 00000000..11c762e3 --- /dev/null +++ b/packages/ws-client-core/src/utils/log.js @@ -0,0 +1,23 @@ +// move the get logger stuff here +/** + * @TODO remove this implmenetation once the test is done + */ +const dummyLogger = (...args) => { + Reflect.apply(console.info, console, ['[jsonql-ws-client-core]', ...args]) +} + +/** + * Make sure there is a log method + * @param {object} opts configuration + * @return {object} opts + */ +const getLogFn = opts => { + const { log } = opts // 1.3.9 if we pass a log method here then we use this + if (!log || typeof log !== 'function') { + opts.log = dummyLogger + } + opts.log('--- wsClientCore config opts ---', opts) + return opts +} + +export { getLogFn } \ No newline at end of file -- Gitee From 02994f9529beb19987cbd2c174d3cb6df48ca8b1 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 21:00:39 +0800 Subject: [PATCH 16/26] clean up all the internal functions and found a few strange things --- packages/@jsonql/ws/index.js | 4 ++- packages/ws-client-core/package.json | 2 +- packages/ws-client-core/src/api.js | 8 ++--- packages/ws-client-core/src/core/generator.js | 18 ++++++---- .../src/core/resolver-methods.js | 36 ++++--------------- .../src/core/setup-auth-methods.js | 33 ++++++++++++----- 6 files changed, 49 insertions(+), 52 deletions(-) diff --git a/packages/@jsonql/ws/index.js b/packages/@jsonql/ws/index.js index 105e315e..926dc0af 100644 --- a/packages/@jsonql/ws/index.js +++ b/packages/@jsonql/ws/index.js @@ -1,7 +1,9 @@ // this is the module entry point for ES6 for client // the main will point to the node.js server side setup -import { wsClientCore } from 'jsonql-ws-client-core' +import { wsClientCore } from '../../ws-client-core' +// 'jsonql-ws-client-core' + import wsClientResolver from './src/ws-client-resolver' import { wsClientAppProps, wsClientConstProps } from './src/options' diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json index c29daf13..4828258e 100644 --- a/packages/ws-client-core/package.json +++ b/packages/ws-client-core/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-ws-client-core", - "version": "0.6.0", + "version": "0.6.1", "description": "This is the jsonql Web Socket client core library for Node and Browser. Not for direct use.", "main": "main.js", "module": "index.js", diff --git a/packages/ws-client-core/src/api.js b/packages/ws-client-core/src/api.js index 1651bae4..6fdb4b63 100644 --- a/packages/ws-client-core/src/api.js +++ b/packages/ws-client-core/src/api.js @@ -4,11 +4,7 @@ // import { injectToFn } from 'jsonql-utils' import { generator } from './core' import { checkWsCoreOptions } from './options' -import { ee, processContract, getLogFn } from './utils' - - - - +import { getEventEmitter, processContract, getLogFn } from './utils' /** * 0.5.0 we break up the wsClientCore in two parts one without the config check @@ -40,7 +36,7 @@ export function wsClientCoreAction(socketClientResolver, config) { * @param {object} socketClientResolver this is the one method export by various clients * @param {object} [defaultOptions={}] 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 {object} the wsClient instance with all the available API + * @return {function} accept a config then return the wsClient instance with all the available API */ export function wsClientCore(socketClientResolver, defaultOptions = {}, constProps = {}) { // we need to inject property to this client later diff --git a/packages/ws-client-core/src/core/generator.js b/packages/ws-client-core/src/core/generator.js index 9fb8c742..4ec2200d 100644 --- a/packages/ws-client-core/src/core/generator.js +++ b/packages/ws-client-core/src/core/generator.js @@ -2,14 +2,16 @@ // we change the interface to return promise from v1.0.3 // this way we make sure the obj return is correct and timely import { setupResolver } from './setup-resolver' +import { injectToFn, chainProcessPromises } from '../utils' import { createResolver, createNamespaceErrorHandler, - createOnReadyhandler, - createOnLoginhandler + createOnReadyhandler } from './resolver-methods' -import { createAuthMethods } from './setup-auth-methods' -import { injectToFn, chainProcessPromises } from '../utils' +import { + createAuthMethods, + createOnLoginhandler +} from './setup-auth-methods' /** * step one get the obj map with the namespace @@ -64,12 +66,14 @@ export function generator(opts, nspMap, ee) { args.push( obj1 => createNamespaceErrorHandler(obj1, ee, nspSet), - obj2 => createOnReadyhandler(obj2, ee, nspSet), + obj2 => createOnReadyhandler(obj2, ee), ) if (enableAuth) { - args.push(obj3 => createOnLoginhandler(obj3, ee, opts)) - args.push(obj4 => createAuthMethods(obj4, ee, opts)) + args.push( + obj3 => createOnLoginhandler(obj3, ee), + obj4 => createAuthMethods(obj4, ee, opts) + ) } // run it diff --git a/packages/ws-client-core/src/core/resolver-methods.js b/packages/ws-client-core/src/core/resolver-methods.js index a5215e77..06cd7eee 100644 --- a/packages/ws-client-core/src/core/resolver-methods.js +++ b/packages/ws-client-core/src/core/resolver-methods.js @@ -7,19 +7,15 @@ // callable api for the developer to setup their front end // the only thing is - when they call they might get an error or // NOT_LOGIN_IN and they can react to this error accordingly -import { JsonqlError, JsonqlValidationError, finalCatch } from 'jsonql-errors' +import { finalCatch } from 'jsonql-errors' import { validateAsync } from 'jsonql-params-validator' import { - ERROR_PROP_NAME, - LOGIN_PROP_NAME, - READY_PROP_NAME, ON_ERROR_PROP_NAME, - ON_LOGIN_PROP_NAME, ON_READY_PROP_NAME } from 'jsonql-constants' import { actionCall } from './action-call' import { createEvt, objDefineProps, isFunc } from '../utils' -import { CB_FN_NAME } from '../options/constants' +// import { CB_FN_NAME } from '../options/constants' /** * create the actual function to send message to server @@ -44,10 +40,10 @@ export function createResolver(ee, namespace, resolverName, params) { * @param {object} obj the client itself * @param {object} ee Event Emitter * @param {object} nspSet namespace keys - * @param {boolean} useCallbackStyle use cb or not + * @param {function} log for debug * @return {object} obj with onError prop */ -export function createNamespaceErrorHandler(obj, ee, nspSet) { +export function createNamespaceErrorHandler(obj, ee, nspSet, log) { // using the onError as name // @TODO we should follow the convention earlier // make this a setter for the obj itself @@ -68,9 +64,10 @@ export function createNamespaceErrorHandler(obj, ee, nspSet) { * @param {object} obj the client itself * @param {object} ee Event Emitter * @param {object} nspSet namespace keys + * @param {function} log for debug * @return {object} obj with onReady prop */ -export function createOnReadyhandler(obj, ee, nspSet) { +export function createOnReadyhandler(obj, ee) { return objDefineProps(obj, ON_READY_PROP_NAME, function onReadyCallbackHandler(onReadyCallback) { if (isFunc(onReadyCallback)) { // reduce it down to just one flat level @@ -79,25 +76,6 @@ export function createOnReadyhandler(obj, ee, nspSet) { }) } -/** - * This event will fire when the socket.io.on('connection') and ws.onopen - * Plus this will check if it's the private namespace that fired the event - * @param {object} obj the client itself - * @param {object} ee Event Emitter - * @param {object} opts configuration - * @return {object} obj with onLogin prop - */ -export function createOnLoginhandler(obj, ee, opts) { - if (opts.enableAuth) { - return objDefineProps(obj, ON_LOGIN_PROP_NAME, function onLoginCallbackHandler(onLoginCallback) { - if (isFunc(onLoginCallback)) { - // only one callback can registered with it, TBC - ee.$only(ON_LOGIN_PROP_NAME, onLoginCallback) - } - }) - } - // just skip it - return obj -} + diff --git a/packages/ws-client-core/src/core/setup-auth-methods.js b/packages/ws-client-core/src/core/setup-auth-methods.js index 5a3fb2d5..43f08d97 100644 --- a/packages/ws-client-core/src/core/setup-auth-methods.js +++ b/packages/ws-client-core/src/core/setup-auth-methods.js @@ -1,5 +1,9 @@ // take out from the resolver-methods -import { LOGIN_EVENT_NAME, LOGOUT_EVENT_NAME } from 'jsonql-constants' +import { + LOGIN_EVENT_NAME, + LOGOUT_EVENT_NAME, + ON_LOGIN_PROP_NAME +} from 'jsonql-constants' import { JsonqlValidationError } from 'jsonql-errors' import { injectToFn, chainFns, isString } from '../utils' @@ -31,11 +35,11 @@ const setupLoginHandler = (obj, ee, opts) => [ * @param {object} opts configuration * @return {object} the modified obj */ -const setupLogoutHandler = (obj, ee, opts) => ( - injectToFn(obj, opts.logoutHandlerName, function logoutHandler(...args) { +const setupLogoutHandler = (obj, ee, opts) => { + return injectToFn(obj, opts.logoutHandlerName, function logoutHandler(...args) { ee.$trigger(LOGOUT_EVENT_NAME, args) }) -) +} /** * Create auth related methods @@ -45,8 +49,21 @@ const setupLogoutHandler = (obj, ee, opts) => ( * @return {object} obj with auth methods if any */ export function createAuthMethods(obj, ee, opts) { - if (opts.enableAuth) { - return chainFns(setupLoginHandler, setupLogoutHandler)(obj, ee, opts) - } - return obj + return chainFns(setupLoginHandler, setupLogoutHandler)(obj, ee, opts) +} + +/** + * This event will fire when the socket.io.on('connection') and ws.onopen + * Plus this will check if it's the private namespace that fired the event + * @param {object} obj the client itself + * @param {object} ee Event Emitter + * @return {object} obj with onLogin prop + */ +export function createOnLoginhandler(obj, ee) { + return objDefineProps(obj, ON_LOGIN_PROP_NAME, function onLoginCallbackHandler(onLoginCallback) { + if (isFunc(onLoginCallback)) { + // only one callback can registered with it, TBC + ee.$only(ON_LOGIN_PROP_NAME, onLoginCallback) + } + }) } -- Gitee From 434907da6a662a5dc933427ee8ccb7ec5babeee8 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 22:50:55 +0800 Subject: [PATCH 17/26] completely rewrote the generator logic --- packages/ws-client-core/src/core/generator.js | 41 +++++++------ .../src/core/resolver-methods.js | 57 +++++++++++-------- .../src/core/setup-auth-methods.js | 55 ++++++++++-------- packages/ws-client-core/src/utils/index.js | 2 - 4 files changed, 82 insertions(+), 73 deletions(-) diff --git a/packages/ws-client-core/src/core/generator.js b/packages/ws-client-core/src/core/generator.js index 4ec2200d..045ead78 100644 --- a/packages/ws-client-core/src/core/generator.js +++ b/packages/ws-client-core/src/core/generator.js @@ -2,28 +2,23 @@ // we change the interface to return promise from v1.0.3 // this way we make sure the obj return is correct and timely import { setupResolver } from './setup-resolver' -import { injectToFn, chainProcessPromises } from '../utils' +import { injectToFn, chainFns } from '../utils' +import { createAuthMethods } from './setup-auth-methods' import { createResolver, createNamespaceErrorHandler, createOnReadyhandler } from './resolver-methods' -import { - createAuthMethods, - createOnLoginhandler -} from './setup-auth-methods' /** * step one get the obj map with the namespace * @param {object} opts configuration - * @param {object} nspMap resolvers index by their namespace * @param {object} ee EventEmitter + * @param {object} nspSet resolvers index by their namespace * @return {promise} resolve the obj mapped, and start the chain */ -function getMappedObj(opts, nspMap, ee) { - let obj = {}; - // let resolverNames = []; - const { nspSet } = nspMap +function generateResolvers(opts, ee, nspSet) { + let obj = {} // const { useCallbackStyle } = opts; // @1.2.1 for (let namespace in nspSet) { let list = nspSet[namespace] @@ -48,7 +43,7 @@ function getMappedObj(opts, nspMap, ee) { } // resolve the obj to start the chain // chain the result to allow the chain processing - return Promise.resolve(obj) + return [ obj, opts, ee, nspSet ] } /** @@ -62,21 +57,23 @@ function getMappedObj(opts, nspMap, ee) { export function generator(opts, nspMap, ee) { const { nspSet } = nspMap const { enableAuth } = opts - let args = [getMappedObj] - - args.push( - obj1 => createNamespaceErrorHandler(obj1, ee, nspSet), - obj2 => createOnReadyhandler(obj2, ee), - ) - + let args = [ + generateResolvers, + createNamespaceErrorHandler, + createOnReadyhandler, + ] if (enableAuth) { args.push( - obj3 => createOnLoginhandler(obj3, ee), - obj4 => createAuthMethods(obj4, ee, opts) + createAuthMethods + ) + } else { + // we just return the obj itself + args.push( + (obj) => obj ) } // run it - const executor = Reflect.apply(chainProcessPromises, null, args) - return executor(opts, nspMap, ee) + const fn = Reflect.apply(chainFns, null, args) + return fn(opts, ee, nspSet) } diff --git a/packages/ws-client-core/src/core/resolver-methods.js b/packages/ws-client-core/src/core/resolver-methods.js index 06cd7eee..8ba3fa70 100644 --- a/packages/ws-client-core/src/core/resolver-methods.js +++ b/packages/ws-client-core/src/core/resolver-methods.js @@ -38,42 +38,49 @@ export function createResolver(ee, namespace, resolverName, params) { * The problem is the namespace can have more than one * and we only have on onError message * @param {object} obj the client itself + * @param {object} opts configuration * @param {object} ee Event Emitter * @param {object} nspSet namespace keys - * @param {function} log for debug - * @return {object} obj with onError prop + * @return {array} [obj, opts, ee] */ -export function createNamespaceErrorHandler(obj, ee, nspSet, log) { - // using the onError as name - // @TODO we should follow the convention earlier - // make this a setter for the obj itself - return objDefineProps(obj, ON_ERROR_PROP_NAME, function namespaceErrorCallbackHandler(namespaceErrorHandler) { - if (isFunc(namespaceErrorHandler)) { - // please note ON_ERROR_PROP_NAME can add multiple listners - for (let namespace in nspSet) { - // 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_PROP_NAME), namespaceErrorHandler) +export function createNamespaceErrorHandler(obj, opts, ee, nspSet) { + return [ + // using the onError as name + // @TODO we should follow the convention earlier + // make this a setter for the obj itself + objDefineProps(obj, ON_ERROR_PROP_NAME, function namespaceErrorCallbackHandler(namespaceErrorHandler) { + if (isFunc(namespaceErrorHandler)) { + // please note ON_ERROR_PROP_NAME can add multiple listners + for (let namespace in nspSet) { + // 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_PROP_NAME), namespaceErrorHandler) + } } - } - }) + }), + opts, + ee + ] } /** * This event will fire when the socket.io.on('connection') and ws.onopen * @param {object} obj the client itself + * @param {object} opts configuration * @param {object} ee Event Emitter - * @param {object} nspSet namespace keys - * @param {function} log for debug - * @return {object} obj with onReady prop + * @return {array} [ obj, opts, ee ] */ -export function createOnReadyhandler(obj, ee) { - return objDefineProps(obj, ON_READY_PROP_NAME, function onReadyCallbackHandler(onReadyCallback) { - if (isFunc(onReadyCallback)) { - // reduce it down to just one flat level - ee.$on(ON_READY_PROP_NAME, onReadyCallback) - } - }) +export function createOnReadyhandler(obj, opts, ee) { + return [ + objDefineProps(obj, ON_READY_PROP_NAME, function onReadyCallbackHandler(onReadyCallback) { + if (isFunc(onReadyCallback)) { + // reduce it down to just one flat level + ee.$on(ON_READY_PROP_NAME, onReadyCallback) + } + }), + opts, + ee + ] } diff --git a/packages/ws-client-core/src/core/setup-auth-methods.js b/packages/ws-client-core/src/core/setup-auth-methods.js index 43f08d97..c6e456dc 100644 --- a/packages/ws-client-core/src/core/setup-auth-methods.js +++ b/packages/ws-client-core/src/core/setup-auth-methods.js @@ -7,16 +7,17 @@ import { import { JsonqlValidationError } from 'jsonql-errors' import { injectToFn, chainFns, isString } from '../utils' + /** * @TODO this is now become unnecessary because the login is a slave to the * http-client - but keep this for now and see what we want to do with it later * break out from createAuthMethods to allow chaining call * @param {object} obj the main client object - * @param {object} ee event emitter * @param {object} opts configuration - * @return {array} modified input + * @param {object} ee event emitter + * @return {array} [ obj, opts, ee ] */ -const setupLoginHandler = (obj, ee, opts) => [ +const setupLoginHandler = (obj, opts, ee) => [ injectToFn(obj, opts.loginHandlerName, function loginHandler(token) { if (token && isString(token)) { return ee.$trigger(LOGIN_EVENT_NAME, [token]) @@ -31,26 +32,17 @@ const setupLoginHandler = (obj, ee, opts) => [ /** * break out from createAuthMethods to allow chaining call - final in chain * @param {object} obj the main client object - * @param {object} ee event emitter * @param {object} opts configuration - * @return {object} the modified obj + * @param {object} ee event emitter + * @return {array} [ obj, ee ] */ -const setupLogoutHandler = (obj, ee, opts) => { - return injectToFn(obj, opts.logoutHandlerName, function logoutHandler(...args) { +const setupLogoutHandler = (obj, opts, ee) => [ + injectToFn(obj, opts.logoutHandlerName, function logoutHandler(...args) { ee.$trigger(LOGOUT_EVENT_NAME, args) - }) -} + }), + ee +] -/** - * Create auth related methods - * @param {object} obj the client itself - * @param {object} ee Event Emitter - * @param {object} opts configuration - * @return {object} obj with auth methods if any - */ -export function createAuthMethods(obj, ee, opts) { - return chainFns(setupLoginHandler, setupLogoutHandler)(obj, ee, opts) -} /** * This event will fire when the socket.io.on('connection') and ws.onopen @@ -61,9 +53,24 @@ export function createAuthMethods(obj, ee, opts) { */ export function createOnLoginhandler(obj, ee) { return objDefineProps(obj, ON_LOGIN_PROP_NAME, function onLoginCallbackHandler(onLoginCallback) { - if (isFunc(onLoginCallback)) { - // only one callback can registered with it, TBC - ee.$only(ON_LOGIN_PROP_NAME, onLoginCallback) - } - }) + if (isFunc(onLoginCallback)) { + // only one callback can registered with it, TBC + ee.$only(ON_LOGIN_PROP_NAME, onLoginCallback) + } + }) +} + +/** + * Create auth related methods + * @param {object} obj the client itself + * @param {object} opts configuration + * @param {object} ee Event Emitter + * @return {object} obj with auth methods if any + */ +export function createAuthMethods(obj, opts, ee) { + return chainFns( + setupLoginHandler, + setupLogoutHandler, + createOnLoginhandler + )(obj, opts, ee) } diff --git a/packages/ws-client-core/src/utils/index.js b/packages/ws-client-core/src/utils/index.js index 4fa59191..3d9402e1 100644 --- a/packages/ws-client-core/src/utils/index.js +++ b/packages/ws-client-core/src/utils/index.js @@ -14,7 +14,6 @@ import { isObjectHasKey, chainFns, chainPromises, - chainProcessPromises, objHasProp, postConfigCheck } from 'jsonql-utils/module' @@ -44,7 +43,6 @@ export { isObjectHasKey, chainFns, chainPromises, - chainProcessPromises, objHasProp, postConfigCheck, -- Gitee From efabcf1989f37fe7f8c4c9b792f0458b35deba6f Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 22:52:38 +0800 Subject: [PATCH 18/26] remove the two not really useful methods --- packages/ws-client-core/package.json | 2 +- packages/ws-client-core/src/core/generator.js | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/ws-client-core/package.json b/packages/ws-client-core/package.json index 4828258e..7fa85c79 100644 --- a/packages/ws-client-core/package.json +++ b/packages/ws-client-core/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-ws-client-core", - "version": "0.6.1", + "version": "0.7.0", "description": "This is the jsonql Web Socket client core library for Node and Browser. Not for direct use.", "main": "main.js", "module": "index.js", diff --git a/packages/ws-client-core/src/core/generator.js b/packages/ws-client-core/src/core/generator.js index 045ead78..cf1562bf 100644 --- a/packages/ws-client-core/src/core/generator.js +++ b/packages/ws-client-core/src/core/generator.js @@ -31,16 +31,6 @@ function generateResolvers(opts, ee, nspSet) { obj = injectToFn(obj, resolverName, setupResolver(namespace, resolverName, params, fn, ee)) } } - // move this two method down to helpers - // we want these methods visible in debug or console.log - obj.devHelpers = { - // this is a helper method for the developer to know the namespace inside - getNsp: () => Object.keys(nspSet), - // simple get version trick - getVer: () => opts.version || 'NOT SET' - // not really necessary because the dev can query the contract - // getResolverNames: () => resolverNames - } // resolve the obj to start the chain // chain the result to allow the chain processing return [ obj, opts, ee, nspSet ] -- Gitee From a56be9598e68f0440d175af62be58674ff5be446 Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 23:07:45 +0800 Subject: [PATCH 19/26] reorganize the generator methods, put related methods together --- packages/ws-client-core/src/core/generator.js | 31 ++--------------- .../src/core/resolver-methods.js | 33 +++++++++++++++++-- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/packages/ws-client-core/src/core/generator.js b/packages/ws-client-core/src/core/generator.js index cf1562bf..3fb8cc6f 100644 --- a/packages/ws-client-core/src/core/generator.js +++ b/packages/ws-client-core/src/core/generator.js @@ -1,41 +1,14 @@ // resolvers generator // we change the interface to return promise from v1.0.3 // this way we make sure the obj return is correct and timely -import { setupResolver } from './setup-resolver' -import { injectToFn, chainFns } from '../utils' +import { chainFns } from '../utils' import { createAuthMethods } from './setup-auth-methods' import { - createResolver, + generateResolvers, createNamespaceErrorHandler, createOnReadyhandler } from './resolver-methods' -/** - * step one get the obj map with the namespace - * @param {object} opts configuration - * @param {object} ee EventEmitter - * @param {object} nspSet resolvers index by their namespace - * @return {promise} resolve the obj mapped, and start the chain - */ -function generateResolvers(opts, ee, nspSet) { - let obj = {} - // const { useCallbackStyle } = opts; // @1.2.1 - for (let namespace in nspSet) { - let list = nspSet[namespace] - for (let resolverName in list) { - // resolverNames.push(resolverName) - let params = list[resolverName] - let fn = createResolver(ee, namespace, resolverName, params) - // this should set as a getter therefore can not be overwrite by accident - // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee) - obj = injectToFn(obj, resolverName, setupResolver(namespace, resolverName, params, fn, ee)) - } - } - // resolve the obj to start the chain - // chain the result to allow the chain processing - return [ obj, opts, ee, nspSet ] -} - /** * prepare the methods * @param {object} opts configuration diff --git a/packages/ws-client-core/src/core/resolver-methods.js b/packages/ws-client-core/src/core/resolver-methods.js index 8ba3fa70..96208f18 100644 --- a/packages/ws-client-core/src/core/resolver-methods.js +++ b/packages/ws-client-core/src/core/resolver-methods.js @@ -9,12 +9,13 @@ // NOT_LOGIN_IN and they can react to this error accordingly import { finalCatch } from 'jsonql-errors' import { validateAsync } from 'jsonql-params-validator' +import { setupResolver } from './setup-resolver' +import { actionCall } from './action-call' +import { createEvt, objDefineProps, isFunc, injectToFn } from '../utils' import { ON_ERROR_PROP_NAME, ON_READY_PROP_NAME } from 'jsonql-constants' -import { actionCall } from './action-call' -import { createEvt, objDefineProps, isFunc } from '../utils' // import { CB_FN_NAME } from '../options/constants' /** @@ -25,7 +26,7 @@ import { createEvt, objDefineProps, isFunc } from '../utils' * @param {object} params from contract * @return {function} resolver */ -export function createResolver(ee, namespace, resolverName, params) { +function createResolver(ee, namespace, resolverName, params) { // note we pass the new withResult=true option return function(...args) { return validateAsync(args, params.params, true) @@ -34,6 +35,32 @@ export function createResolver(ee, namespace, resolverName, params) { } } +/** + * step one get the obj map with the namespace + * @param {object} opts configuration + * @param {object} ee EventEmitter + * @param {object} nspSet resolvers index by their namespace + * @return {promise} resolve the obj mapped, and start the chain + */ +export function generateResolvers(opts, ee, nspSet) { + let obj = {} + // const { useCallbackStyle } = opts; // @1.2.1 + for (let namespace in nspSet) { + let list = nspSet[namespace] + for (let resolverName in list) { + // resolverNames.push(resolverName) + let params = list[resolverName] + let fn = createResolver(ee, namespace, resolverName, params) + // this should set as a getter therefore can not be overwrite by accident + // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee) + obj = injectToFn(obj, resolverName, setupResolver(namespace, resolverName, params, fn, ee)) + } + } + // resolve the obj to start the chain + // chain the result to allow the chain processing + return [ obj, opts, ee, nspSet ] +} + /** * The problem is the namespace can have more than one * and we only have on onError message -- Gitee From 80c5227945e37bd94c42f344526ea64b39bbf98f Mon Sep 17 00:00:00 2001 From: joelchu Date: Tue, 3 Mar 2020 23:26:40 +0800 Subject: [PATCH 20/26] update build script --- .../@jsonql/ws/dist/jsonql-ws-client.umd.js | 2 +- packages/@jsonql/ws/main.js | 8031 +---------------- packages/@jsonql/ws/main.js.map | 2 +- packages/@jsonql/ws/module.js | 5 +- packages/@jsonql/ws/package.json | 1 - packages/@jsonql/ws/rollup.config.js | 23 +- 6 files changed, 22 insertions(+), 8042 deletions(-) diff --git a/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js b/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js index d68b2b05..0cc7ccbc 100644 --- a/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js +++ b/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js @@ -1,2 +1,2 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).jsonqlWsClient=e()}(this,(function(){"use strict";var t=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 406},r.name.get=function(){return"Jsonql406Error"},Object.defineProperties(e,r),e}(Error),e=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"Jsonql500Error"},Object.defineProperties(e,r),e}(Error),r=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 403},r.name.get=function(){return"JsonqlForbiddenError"},Object.defineProperties(e,r),e}(Error),n=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlAuthorisationError"},Object.defineProperties(e,r),e}(Error),o=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlContractAuthError"},Object.defineProperties(e,r),e}(Error),a=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"JsonqlResolverAppError"},Object.defineProperties(e,r),e}(Error),i=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 404},r.name.get=function(){return"JsonqlResolverNotFoundError"},Object.defineProperties(e,r),e}(Error),u=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlEnumError"},Object.defineProperties(e,r),e}(Error),c=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlTypeError"},Object.defineProperties(e,r),e}(Error),s=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlCheckerError"},Object.defineProperties(e,r),e}(Error),f=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(e,r),e}(Error),l=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0},statusCode:{configurable:!0}};return r.name.get=function(){return"JsonqlError"},r.statusCode.get=function(){return-1},Object.defineProperties(e,r),e}(Error),p=function(t){function e(r,n){t.call(this,n),this.statusCode=r,this.className=e.name}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlServerError"},Object.defineProperties(e,r),e}(Error);function h(h){if(Array.isArray(h))throw new f("",h);var v=h.message||"No message",g=h.detail||h;switch(!0){case h instanceof t:throw new t(v,g);case h instanceof e:throw new e(v,g);case h instanceof r:throw new r(v,g);case h instanceof n:throw new n(v,g);case h instanceof o:throw new o(v,g);case h instanceof a:throw new a(v,g);case h instanceof i:throw new i(v,g);case h instanceof u:throw new u(v,g);case h instanceof c:throw new c(v,g);case h instanceof s:throw new s(v,g);case h instanceof f:throw new f(v,g);case h instanceof p:throw new p(v,g);default:throw new l(v,g)}}var v="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},g="object"==typeof v&&v&&v.Object===Object&&v,d="object"==typeof self&&self&&self.Object===Object&&self,y=g||d||Function("return this")(),b=y.Symbol;function _(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var a=Array(o);++n-1;);return r}(n,o),function(t,e){for(var r=t.length;r--&&R(e,t[r],0)>-1;);return r}(n,o)+1).join("")}var Q=function(t){return!!m(t)||null!=t&&""!==G(t)};function X(t){return function(t){return"number"==typeof t||T(t)&&"[object Number]"==$(t)}(t)&&t!=+t}function Z(t){return"string"==typeof t||!m(t)&&T(t)&&"[object String]"==$(t)}var tt=function(t){return!Z(t)&&!X(parseFloat(t))},et=function(t){return""!==G(t)&&Z(t)},rt=function(t){return null!=t&&"boolean"==typeof t},nt=function(t,e){return void 0===e&&(e=!0),void 0!==t&&""!==t&&""!==G(t)&&(!1===e||!0===e&&null!==t)},ot=function(t){switch(t){case"number":return tt;case"string":return et;case"boolean":return rt;default:return nt}},at=function(t,e){return void 0===e&&(e=""),!!m(t)&&(""===e||""===G(e)||!(t.filter((function(t){return!ot(e)(t)})).length>0))},it=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var e=t.replace("array.<","").replace(">","");return e.indexOf("|")?e.split("|"):[e]}return!1},ut=function(t,e){var r=t.arg;return e.length>1?!r.filter((function(t){return!(e.length>e.filter((function(e){return!ot(e)(t)})).length)})).length:e.length>e.filter((function(t){return!at(r,t)})).length};function ct(t,e){return function(r){return t(e(r))}}var st=ct(Object.getPrototypeOf,Object),ft=Function.prototype,lt=Object.prototype,pt=ft.toString,ht=lt.hasOwnProperty,vt=pt.call(Object);function gt(t){if(!T(t)||"[object Object]"!=$(t))return!1;var e=st(t);if(null===e)return!0;var r=ht.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&pt.call(r)==vt}var dt,yt=function(t,e,r){for(var n=-1,o=Object(t),a=r(t),i=a.length;i--;){var u=a[dt?i:++n];if(!1===e(o[u],u,o))break}return t};function bt(t){return T(t)&&"[object Arguments]"==$(t)}var _t=Object.prototype,mt=_t.hasOwnProperty,wt=_t.propertyIsEnumerable,jt=bt(function(){return arguments}())?bt:function(t){return T(t)&&mt.call(t,"callee")&&!wt.call(t,"callee")};var Ot="object"==typeof exports&&exports&&!exports.nodeType&&exports,St=Ot&&"object"==typeof module&&module&&!module.nodeType&&module,kt=St&&St.exports===Ot?y.Buffer:void 0,Et=(kt?kt.isBuffer:void 0)||function(){return!1},$t=/^(?:0|[1-9]\d*)$/;function Tt(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&$t.test(t))&&t>-1&&t%1==0&&t-1&&t%1==0&&t<=9007199254740991}var Pt={};Pt["[object Float32Array]"]=Pt["[object Float64Array]"]=Pt["[object Int8Array]"]=Pt["[object Int16Array]"]=Pt["[object Int32Array]"]=Pt["[object Uint8Array]"]=Pt["[object Uint8ClampedArray]"]=Pt["[object Uint16Array]"]=Pt["[object Uint32Array]"]=!0,Pt["[object Arguments]"]=Pt["[object Array]"]=Pt["[object ArrayBuffer]"]=Pt["[object Boolean]"]=Pt["[object DataView]"]=Pt["[object Date]"]=Pt["[object Error]"]=Pt["[object Function]"]=Pt["[object Map]"]=Pt["[object Number]"]=Pt["[object Object]"]=Pt["[object RegExp]"]=Pt["[object Set]"]=Pt["[object String]"]=Pt["[object WeakMap]"]=!1;var zt,Nt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Ct=Nt&&"object"==typeof module&&module&&!module.nodeType&&module,xt=Ct&&Ct.exports===Nt&&g.process,Rt=function(){try{var t=Ct&&Ct.require&&Ct.require("util").types;return t||xt&&xt.binding&&xt.binding("util")}catch(t){}}(),qt=Rt&&Rt.isTypedArray,Mt=qt?(zt=qt,function(t){return zt(t)}):function(t){return T(t)&&At(t.length)&&!!Pt[$(t)]},Ft=Object.prototype.hasOwnProperty;function Lt(t,e){var r=m(t),n=!r&&jt(t),o=!r&&!n&&Et(t),a=!r&&!n&&!o&&Mt(t),i=r||n||o||a,u=i?function(t,e){for(var r=-1,n=Array(t);++r-1},Xt.prototype.set=function(t,e){var r=this.__data__,n=Gt(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};var Zt,te=y["__core-js_shared__"],ee=(Zt=/[^.]+$/.exec(te&&te.keys&&te.keys.IE_PROTO||""))?"Symbol(src)_1."+Zt:"";var re=Function.prototype.toString;function ne(t){if(null!=t){try{return re.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var oe=/^\[object .+?Constructor\]$/,ae=Function.prototype,ie=Object.prototype,ue=ae.toString,ce=ie.hasOwnProperty,se=RegExp("^"+ue.call(ce).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function fe(t){return!(!Dt(t)||function(t){return!!ee&&ee in t}(t))&&(Ht(t)?se:oe).test(ne(t))}function le(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return fe(r)?r:void 0}var pe=le(y,"Map"),he=le(Object,"create");var ve=Object.prototype.hasOwnProperty;var ge=Object.prototype.hasOwnProperty;function de(t){var e=-1,r=null==t?0:t.length;for(this.clear();++eu))return!1;var s=a.get(t);if(s&&a.get(e))return s==e;var f=-1,l=!0,p=2&r?new me:void 0;for(a.set(t,e),a.set(e,t);++fe.type.filter((function(t){var e;return void 0===r||(!1!==(e=it(t))?!ut({arg:r},e):!ot(t)(r))})).length)})).length}return!1},dr=function(t,e){var r,n,o,a,i;switch(!0){case"object"===t:return o=(n=e).arg,a=n.param,i=[o],Array.isArray(a.keys)&&a.keys.length&&i.push(a.keys),!Reflect.apply(gr,null,i);case"array"===t:return!at(e.arg);case!1!==(r=it(t)):return!ut(e,r);default:return!ot(t)(e.arg)}},yr=function(t,e){return void 0!==t?t:!0===e.optional&&void 0!==e.defaultvalue?e.defaultvalue:null},br=function(t,e,r){var n;void 0===r&&(r=!1);var o=function(t,e){if(!at(e))throw new l("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===e.length)return[];if(!at(t))throw new l("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==e.length:return t.map((function(t,r){return{arg:t,index:r,param:e[r]}}));case!0===e[0].variable:var r=e[0].type;return t.map((function(t,n){return{arg:t,index:n,param:e[n]||{type:r,name:"_"}}}));case t.lengthe.length:var n=e.length,o=["any"];return t.map((function(t,r){var a=r>=n||!!e[r].optional,i=e[r]||{type:o,name:"_"+r};return{arg:a?yr(t,i):t,index:r,param:i,optional:a}}));default:throw new l("Could not understand your arguments and parameter structure!",{args:t,params:e})}}(t,e),a=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var e=t.arg,r=t.param;return!!Q(e)&&!(r.type.length>r.type.filter((function(e){return dr(e,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(e){return dr(e,t)})).length)}));return r?((n={}).error=a,n.data=o.map((function(t){return t.arg})),n):a},_r=function(){try{var t=le(Object,"defineProperty");return t({},"",{}),t}catch(t){}}();function mr(t,e,r){"__proto__"==e&&_r?_r(t,e,{configurable:!0,enumerable:!0,value:r,writable:!0}):t[e]=r}function wr(t,e,r){(void 0===r||Kt(t[e],r))&&(void 0!==r||e in t)||mr(t,e,r)}var jr="object"==typeof exports&&exports&&!exports.nodeType&&exports,Or=jr&&"object"==typeof module&&module&&!module.nodeType&&module,Sr=Or&&Or.exports===jr?y.Buffer:void 0,kr=Sr?Sr.allocUnsafe:void 0;function Er(t,e){var r,n,o=e?(r=t.buffer,n=new r.constructor(r.byteLength),new Oe(n).set(new Oe(r)),n):t.buffer;return new t.constructor(o,t.byteOffset,t.length)}var $r=Object.create,Tr=function(){function t(){}return function(e){if(!Dt(e))return{};if($r)return $r(e);t.prototype=e;var r=new t;return t.prototype=void 0,r}}();function Ar(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var Pr=Object.prototype.hasOwnProperty;function zr(t,e,r){var n=t[e];Pr.call(t,e)&&Kt(n,r)&&(void 0!==r||e in t)||mr(t,e,r)}var Nr=Object.prototype.hasOwnProperty;function Cr(t){if(!Dt(t))return function(t){var e=[];if(null!=t)for(var r in Object(t))e.push(r);return e}(t);var e=Jt(t),r=[];for(var n in t)("constructor"!=n||!e&&Nr.call(t,n))&&r.push(n);return r}function xr(t){return Vt(t)?Lt(t,!0):Cr(t)}function Rr(t){return function(t,e,r,n){var o=!r;r||(r={});for(var a=-1,i=e.length;++a0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(Wr);function Ur(t,e){return Ir(function(t,e,r){return e=Lr(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,a=Lr(n.length-e,0),i=Array(a);++o1?e[n-1]:void 0,a=n>2?e[2]:void 0;for(o=Dr.length>3&&"function"==typeof o?(n--,o):void 0,a&&function(t,e,r){if(!Dt(r))return!1;var n=typeof e;return!!("number"==n?Vt(r)&&Tt(e,r.length):"string"==n&&e in r)&&Kt(r[e],t)}(e[0],e[1],a)&&(o=n<3?void 0:o,n=1),t=Object(t);++r0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return Reflect.apply(e,null,sn(t))}),Reflect.apply(t,null,r))}};function vn(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return t.then((function(t){return e(t)}))}),Reflect.apply(t,null,r))}}function gn(t,e,r,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,e)&&Object.defineProperty(t,e,{set:r,get:null===n?function(){return null}:n}),t}function dn(t,e,r,n){void 0===n&&(n=!1);var o=function(t,e){var r=Object.getOwnPropertyDescriptor(t,e);return void 0!==r&&r.value?r.value:r}(t,e);return!1===n&&void 0!==o||Object.defineProperty(t,e,{value:r,writable:n}),t}function yn(t){return!!fn(t,"socket")&&t.socket}var bn=function(t){void 0===t&&(t=!1);var e=Date.now();return t?Math.floor(e/1e3):e};function _n(t,e,r){if(void 0===e&&(e=[]),void 0===r&&(r=!1),Z(t)&&m(e)){var n=function(t){var e;return(e={}).args=t,e}(e);return!0===r?n:function(t,e){var r;return(r={})[t]=e,r.TS=[bn()],r}(t,n)}throw new f("[createQuery] expect resolverName to be string and args to be array!",{resolverName:t,args:e})}var mn=new WeakMap,wn=new WeakMap;var jn=function(){this.__suspend__=null,this.queueStore=new Set},On={$suspend:{configurable:!0},$queues:{configurable:!0}};On.$suspend.set=function(t){var e=this;if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value!");var r=this.__suspend__;this.__suspend__=t,this.logger("($suspend)","Change from "+r+" --\x3e "+t),!0===r&&!1===t&&setTimeout((function(){e.release()}),1)},jn.prototype.$queue=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return!0===this.__suspend__&&(this.logger("($queue)","added to $queue",t),this.queueStore.add(t)),this.__suspend__},On.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},jn.prototype.release=function(){var t=this,e=this.queueStore.size;if(this.logger("(release)","Release was called "+e),e>0){var r=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",r),r.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(jn.prototype,On);var Sn=function(t){function e(e){if("function"!=typeof e)throw new Error("Just die here the logger is not a function!");t.call(this,{logger:e})}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(e.prototype,r),e}(function(t){function e(e){void 0===e&&(e={}),t.call(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={$done:{configurable:!0}};return e.prototype.logger=function(){},e.prototype.$on=function(t,e,r){var n=this;void 0===r&&(r=null);this.validate(t,e);var o=this.takeFromStore(t);if(!1===o)return this.logger("($on)",t+" callback is not in lazy store"),this.addToNormalStore(t,"on",e,r);this.logger("($on)",t+" found in lazy store");var a=0;return o.forEach((function(o){var i=o[0],u=o[1],c=o[2];if(c&&"on"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);n.logger("($on)","call run on "+t),n.run(e,i,r||u),a+=n.addToNormalStore(t,"on",e,r||u)})),a},e.prototype.$once=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=this.takeFromStore(t);this.normalStore;if(!1===n)return this.logger("($once)",t+" not in the lazy store"),this.addToNormalStore(t,"once",e,r);this.logger("($once)",n);var o=Array.from(n)[0],a=o[0],i=o[1],u=o[2];if(u&&"once"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);this.logger("($once)","call run for "+t),this.run(e,a,r||i),this.$off(t)},e.prototype.$only=function(t,e,r){var n=this;void 0===r&&(r=null),this.validate(t,e);var o=!1,a=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger("($only)",t+" add to store"),o=this.addToNormalStore(t,"only",e,r)),!1!==a)&&(this.logger("($only)",t+" found data in lazy store to execute"),Array.from(a).forEach((function(o){var a=o[0],i=o[1],u=o[2];if(u&&"only"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);n.logger("($only)","call run for "+t),n.run(e,a,r||i)})));return o},e.prototype.$onlyOnce=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=!1,o=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger("($onlyOnce)",t+" add to store"),n=this.addToNormalStore(t,"onlyOnce",e,r)),!1!==o){this.logger("($onlyOnce)",o);var a=Array.from(o)[0],i=a[0],u=a[1],c=a[2];if(c&&"onlyOnce"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);this.logger("($onlyOnce)","call run for "+t),this.run(e,i,r||u),this.$off(t)}return n},e.prototype.$replace=function(t,e,r,n){if(void 0===r&&(r=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,e),Reflect.apply(o,this,[t,e,r])}throw new Error(n+" is not supported!")},e.prototype.$trigger=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,a=this.normalStore;if(this.logger("($trigger)","normalStore",a),a.has(t)){var i=this.$queue(t,e,r,n);if(this.logger("($trigger)",t,"found; add to queue: ",i),!0===i)return this.logger("($trigger)",t,"not executed. Exit now."),!1;for(var u=Array.from(a.get(t)),c=u.length,s=!1,f=0;f0;)n[o]=arguments[o+2];if(t.has(e)?(this.logger("(addToStore)",e+" existed"),r=t.get(e)):(this.logger("(addToStore)","create new Set for "+e),r=new Set),n.length>2)if(Array.isArray(n[0])){var a=n[2];this.checkTypeInLazyStore(e,a)||r.add(n)}else this.checkContentExist(n,r)||(this.logger("(addToStore)","insert new",n),r.add(n));else r.add(n);return t.set(e,r),[t,r.size]},e.prototype.checkContentExist=function(t,e){return!!Array.from(e).filter((function(e){return e[0]===t[0]})).length},e.prototype.checkTypeInStore=function(t,e){this.validateEvt(t,e);var r=this.$get(t,!0);return!1===r||!r.filter((function(t){var r=t[3];return e!==r})).length},e.prototype.checkTypeInLazyStore=function(t,e){this.validateEvt(t,e);var r=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",r),!!r&&!!Array.from(r).filter((function(t){return t[2]!==e})).length},e.prototype.addToNormalStore=function(t,e,r,n){if(void 0===n&&(n=null),this.logger("(addToNormalStore)",t,e,"try to add to normal store"),this.checkTypeInStore(t,e)){this.logger("(addToNormalStore)",e+" can add to "+t+" normal store");var o=this.hashFnToKey(r),a=[this.normalStore,t,o,r,n,e],i=Reflect.apply(this.addToStore,this,a),u=i[0],c=i[1];return this.normalStore=u,c}return!1},e.prototype.addToLazyStore=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(e),r];n&&o.push(n);var a=Reflect.apply(this.addToStore,this,o),i=a[0],u=a[1];return this.lazyStore=i,u},e.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},r.normalStore.set=function(t){mn.set(this,t)},r.normalStore.get=function(){return mn.get(this)},r.lazyStore.set=function(t){wn.set(this,t)},r.lazyStore.get=function(){return wn.get(this)},e.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,e){return(t=(t<<5)-t+e.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(e.prototype,r),e}(jn)));function kn(t){var e,r,n=t.contract;return t.enableAuth?function(t,e){void 0===e&&(e=!1);var r=yn(t);if(!1===r){if(e)return t;throw new l("socket not found in contract!")}var n,o={},a=0;for(var i in r){var u=r[i],c=u.namespace;c&&(o[c]||(++a,o[c]={}),o[c][i]=u,n||u.public&&(n=c))}return{size:a,nspSet:o,publicNamespace:n}}(n):((r={}).nspSet=((e={}).jsonql=function(t){var e=yn(t);if(!1!==e)return e;throw new i("Missing property in contract!")}(n),e),r.publicNamespace="jsonql",r)}var En=function(t,e){sn(e).forEach((function(e){t.$off(ln(e,"emit"))}))};function $n(t,e,r){fn(t,"error")?r(t.error):fn(t,"data")?e(t.data):r({message:"UKNNOWN RESULT!",error:t})}function Tn(t,e,r,n,o){void 0===o&&(o=[]);var a=ln(e,"emit"),i=n?"result":"onResult";return t.$trigger(a,[r,sn(o)]),new Promise((function(n,o){t.$on(ln(e,r,i),(function(t){$n(t,n,o)}))}))}var An=function(t,e,r,n,o,a){return gn(t,"send",(function(t){var i=a?"error":"onError";an(sn(t),o.params,!0).then((function(o){if(!o.error||!o.error.length)return Tn(e,r,n,a,t);e.$call(ln(r,n,i),[new f(n,o.error)])})).catch((function(t){e.$call(ln(r,n,i),[new f(n,t)])}))}),(function(){return function(){for(var t=[],i=arguments.length;i--;)t[i]=arguments[i];return an(t,o.params,!0).then((function(t){return Tn(e,r,n,a,t)})).catch(h)}}))};function Pn(t,e,r,n,o){return[dn(t,"on",(function(t,o){if(on(t)&&pn(o))switch(t){case"result":e.$on(ln(r,n,"onResult"),(function(t){$n(t,o,(function(t){e.$trigger(ln(r,n,"onError"),t)}))}));break;case"message":e.$only(ln(r,n,"onMessage"),(function(t){$n(t,o,(function(t){e.$trigger(ln(r,n,"onError"),t)}))}));break;case"ready":e.$only(ln(r,n,"onError"),o);break;default:e.$trigger(ln(r,n,"onError"),new l(n,"Unknown event name "+t+"!"))}})),e,r,n,o]}var zn=function(t,e,r,n,o,a){return[dn(t,"myNamespace",r),e,r,n,o,a]},Nn=function(t,e,r,n,o,a){return[gn(t,"onResult",(function(t){pn(t)&&e.$on(ln(r,n,"onResult"),(function(o){$n(o,t,(function(t){e.$trigger(ln(r,n,"onError"),t)}))}))})),e,r,n,o,a]},Cn=function(t,e,r,n,o,a){return[gn(t,"onMessage",(function(t){if(pn(t)){e.$only(ln(r,n,"onMessage"),(function(o){$n(o,t,(function(t){e.$trigger(ln(r,n,"onError"),t)}))}))}})),e,r,n,o,a]},xn=function(t,e,r,n,o,a){return[gn(t,"onError",(function(t){pn(t)&&e.$only(ln(r,n,"onError"),t)})),e,r,n,o,a]};function Rn(t,e,r,n,o,a){var i=[zn];a?i.push(Pn):i.push(Nn,Cn,xn),i.push(An);var u=Reflect.apply(hn,null,i);return Reflect.apply(u,null,[n,o,t,e,r,a])}function qn(t,e,r,n,o){return function(){for(var a=[],i=arguments.length;i--;)a[i]=arguments[i];return an(a,n.params,!0).then((function(n){return Tn(t,e,r,o,n)})).catch(h)}}var Mn,Fn,Ln=function(t,e,r){return[dn(t,r.loginHandlerName,(function(t){if(t&&on(t))return e.$trigger("__login__",[t]);throw new f(r.loginHandlerName,"Unexpected token "+t)})),e,r]},Wn=function(t,e,r){return dn(t,r.logoutHandlerName,(function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];e.$trigger("__logout__",t)}))};function Jn(t,e,r){var n={},o=e.nspSet,a=t.useCallbackStyle;for(var i in o){var u=o[i];for(var c in u){var s=u[c];n=dn(n,c,Rn(i,c,s,qn(r,i,c,s,a),r,a))}}return n.devHelpers={getNsp:function(){return Object.keys(o)},getVer:function(){return t.version||"NOT SET"}},Promise.resolve(n)}function In(t,e,r){var n=e.nspSet,o=t.useCallbackStyle,a=t.enableAuth,i=[Jn];return o?i.push((function(t){return function(t,e,r,n){return dn(t,"on",(function(t,n){if(on(t)&&pn(n))switch(t){case"error":for(var o in r)e.$on(ln(o,"error"),n);break;case"login":e.$only("login",n);break;case"ready":e.$on("ready",n);break;default:e.$trigger("error",new l("on","Unknown event name "+t+"!"))}}))}(t,r,n)})):(i.push((function(t){return function(t,e,r){return gn(t,"onError",(function(t){if(pn(t))for(var n in r)e.$on(ln(n,"onError"),t)}))}(t,r,n)}),(function(t){return function(t,e,r){return gn(t,"onReady",(function(t){pn(t)&&e.$on("onReady",t)}))}(t,r)})),a&&i.push((function(e){return function(t,e,r){return r.enableAuth?gn(t,"onLogin",(function(t){pn(t)&&e.$only("onLogin",t)})):t}(e,r,t)}))),a&&i.push((function(e){return function(t,e,r){return r.enableAuth?hn(Ln,Wn)(t,e,r):t}(e,r,t)})),Reflect.apply(vn,null,i)(t,e,r)}var Un=["roundtip","handshake"],Dn={useCallbackStyle:un(!1,["boolean"]),loginHandlerName:un("login",["string"]),logoutHandlerName:un("logout",["string"]),loginMethod:un("handshake",["string"],(Mn={},Mn.enumv=Un,Mn)),useJwt:un(!0,["boolean","string"]),authStrKey:un(null,["string"]),hostname:un(!1,["string"]),namespace:un("jsonql",["string"]),wsOptions:un({},["object"]),contract:un({},["object"],(Fn={},Fn.checker=function(t){return!!function(t){return gt(t)&&(fn(t,"query")||fn(t,"mutation")||fn(t,"socket"))}(t)&&t},Fn)),enableAuth:un(!1,["boolean"]),token:un(!1,["string"])},Hn={eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:""};function Vn(t){return Promise.resolve(t).then((function(t){var e;return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new f(t)}}()),t.wssPath=(e=[t.hostname,t.namespace].join("/"),"ws"===t.serverType?e.replace("http://","ws://"):e),t}))}function Bn(t,e,r){return function(t,e,r){var n=Object.assign(Hn,r),o=Object.assign(Dn,e);return cn(t,o,n)}(t,e,r).then(Vn)}var Yn=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];Reflect.apply(console.info,console,["[jsonql-ws-client-core]"].concat(t))},Kn=function(t){var e=t.log,r=t.eventEmitter;return e("CHECKED_KEY",t.__checked__),r?(e("eventEmitter is:",r.name),r):(e("Create a new Event Emitter"),new Sn(t.log))},Gn=function(t){var e=t.log;return e&&"function"==typeof e||(t.log=Yn),t.log("--- wsClientCore config opts ---",t),t};function Qn(t,e,r){return void 0===e&&(e={}),void 0===r&&(r={}),function(n){return void 0===n&&(n={}),Bn(n,e,r).then((function(e){return function(t,e){return Promise.resolve(e).then(Gn).then((function(t){return{opts:t,nspMap:kn(t),ee:Kn(t)}})).then((function(e){var r=e.opts,n=e.nspMap,o=e.ee;return t(r,n,o)})).then((function(t){return In(t.opts,t.nspMap,t.ee)})).catch((function(t){console.error("jsonql-ws-core-client init error",t)}))}(t,e)}))}}var Xn=null;"undefined"!=typeof WebSocket?Xn=WebSocket:"undefined"!=typeof MozWebSocket?Xn=MozWebSocket:void 0!==v?Xn=v.WebSocket||v.MozWebSocket:"undefined"!=typeof window?Xn=window.WebSocket||window.MozWebSocket:"undefined"!=typeof self&&(Xn=self.WebSocket||self.MozWebSocket);var Zn=function(t){var e=t.toLowerCase();return e.indexOf("http")>-1?e.indexOf("https")>-1?e.replace("https","wss"):e.replace("http","ws"):e};function to(t,e){return void 0===e&&(e=!1),!1===e?function(e){return new t(Zn(e))}:function(e,r){var n=Zn(e),o=r&&"string"==typeof r?n+"?token="+r:n;try{return new t(o)}catch(t){return console.error("WebSocket Connection Error",t),!1}}}function eo(t,e){var r=e.hostname,n=e.wssPath,o=e.wsOptions;return(0,e.nspClient)(t?[r,t].join("/"):n,o)}var ro=function(t,e,r){var n=r.useCallbackStyle,o=r.log,a=n?"error":"onError",i=n?"result":"onResult";e.$only(ln(t,"emit"),(function(r,n){o("[notLoginHandler] hijack the ws call",t,r,n);var u={message:"NOT LOGIN"};e.$call(ln(t,r,a),[u]),e.$call(ln(t,r,i),[{error:u}])}))};function no(t,e,r,n,o,a){var i=function(t){return t.length>1&&t[0]}(o),u=!1,c=t.log;o.forEach((function(o){if(u=i===o,a[o]){c("[call bindWsHandler]",u,o);var s=[o,a[o],r,u,t];if("socket.io"===t.serverType){var f=e.nspSet;s.push(f[o])}Reflect.apply(n,null,s)}else ro(o,r,t)})),r.$on("__logout__",(function(){c("LOGOUT_EVENT_NAME"),function(t,e,r,n){void 0===n&&(n={});var o=n.useCallbackStyle?"error":"onError";e.forEach((function(e){t.$call(ln(e,o),[{message:r,namespace:e}])}))}(r,o,"__logout__"),o.forEach((function(e){En(r,e),a[e]=!1,ro(e,r,t)}))}))}var oo=["__reply__","__event__","__data__"],ao=function(t){var e,r=t.data;if(!1!==(e=function(t){var e=t.data;return!!e&&(oo.filter((function(t){return fn(e,t)})).length===oo.length&&e)}(on(r)?JSON.parse(r):r)))return{resolverName:e.__event__,data:e.__data__,type:e.__reply__};throw new l("payload can not be decoded",t)},io=function(t,e,r,n,o){var a=[e];r&&a.push(r),a.push(o);var i=Reflect.apply(ln,null,a),u=n.data||n;t.$trigger(i,[u])};function uo(t,e,r,n,o){var a=o.useCallbackStyle,i=o.log;i("wsMainHandler log test");var u=a?"ready":"onReady",c=a?"login":"onLogin",s=a?"message":"onMessage",f=a?"result":"onResult",l=a?"error":"onError";e.onopen=function(){i("ws.onopen listened"),r.$call(u,t),n&&(i("isPrivate and fire the "+c),r.$call(c,t)),r.$only(ln(t,"emit"),(function(t,r){i("calling server",t,r),e.send(function(t,e,r){return void 0===e&&(e=[]),void 0===r&&(r=!1),JSON.stringify(_n(t,e,r))}(t,r))}))},e.onmessage=function(e){try{var n=ao(e),o=n.resolverName,a=n.type;switch(i("Hear from server",a,n),a){case"emit":var u=ln(t,o,s),c=r.$trigger(u,[n]);i("EMIT_REPLY_TYPE",u,c);break;case"acknowledge":var p=ln(t,o,f);r.$trigger(p,[n]);break;case"error":i("ERROR_TYPE"),io(r,t,o,n,l);break;default:i("Unhandled event!",n),io(r,t,o,n,l)}}catch(e){console.error("ws.onmessage error",e),io(r,t,!1,e,l)}},e.onclose=function(){i("ws.onclose callback")},r.$on("__logout__",(function(){try{i("terminate ws connection"),e.terminate()}catch(t){console.error("ws.terminate error",t)}}))}var co=function(t,e,r){var n,o=e.nspSet,a=e.publicNamespace,i=!1,u=[],c={};if(t.enableAuth)i=!0,c=(u=function(t,e){var r=[];for(var n in t)n===e?r[1]=n:r[0]=n;return r}(o,a)).map((function(e,n){var o,a,i;return 0===n?r?(t.token=r,(o={})[e]=function(t,e){var r=e.hostname,n=e.wssPath,o=e.token,a=e.wsOptions,i=e.nspAuthClient,u=t?[r,t].join("/"):n;if(o&&"string"!=typeof o)throw new Error("Expect token to be string, but got "+o);return i(u,o,a)}(e,t),o):((a={})[e]=!1,a):((i={})[e]=eo(e,t),i)})).reduce((function(t,e){return Object.assign(t,e)}),{});else{var s=(n=o,Object.keys(n)[0]);u.push(s),c[s]=eo(!1,t)}return{nsps:c,namespaces:u,login:i}};var so=function(t){var e=to(t),r=to(t,!0);return function(t,n,o){t.nspClient=e,t.nspAuthClient=r;var a=t.log;return a&&"function"==typeof a&&(a("@jsonql/ws ee",o.name),a("@jsonql/ws createClientResolver",t)),function(t,e,r){var n=[t,e,r,uo],o=t.token,a=t.log,i=co(t,e,o),u=i.nsps,c=i.namespaces,s=i.login;return Reflect.apply(no,null,n.concat([c,u])),s&&r.$only("__login__",(function(o){a("createClient LOGIN_EVENT_NAME"),En(r,c);var i=co(t,e,o);Reflect.apply(no,null,n.concat([i.namespaces,i.nsps]))})),{opts:t,nspMap:e,ee:r}}(t,n,o)}}(Xn),fo={version:"version: 1.1.0 module: umd",serverType:"ws"},lo={};return function(t,e){return void 0===t&&(t={}),void 0===e&&(e={}),Qn(so,lo,Object.assign(fo,e))(t)}})); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).jsonqlWsClient=e()}(this,(function(){"use strict";var t="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},e="object"==typeof t&&t&&t.Object===Object&&t,r="object"==typeof self&&self&&self.Object===Object&&self,n=e||r||Function("return this")(),o=n.Symbol;function u(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var u=Array(o);++n-1;);return r}(n,o),function(t,e){for(var r=t.length;r--&&j(e,t[r],0)>-1;);return r}(n,o)+1).join("")}var M=function(t){return!!i(t)||null!=t&&""!==R(t)};function F(t){return function(t){return"number"==typeof t||v(t)&&"[object Number]"==h(t)}(t)&&t!=+t}function L(t){return"string"==typeof t||!i(t)&&v(t)&&"[object String]"==h(t)}var W=function(t){return!L(t)&&!F(parseFloat(t))},J=function(t){return""!==R(t)&&L(t)},I=function(t){return null!=t&&"boolean"==typeof t},D=function(t,e){return void 0===e&&(e=!0),void 0!==t&&""!==t&&""!==R(t)&&(!1===e||!0===e&&null!==t)},U=function(t){switch(t){case"number":return W;case"string":return J;case"boolean":return I;default:return D}},V=function(t,e){return void 0===e&&(e=""),!!i(t)&&(""===e||""===R(e)||!(t.filter((function(t){return!U(e)(t)})).length>0))},B=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var e=t.replace("array.<","").replace(">","");return e.indexOf("|")?e.split("|"):[e]}return!1},H=function(t,e){var r=t.arg;return e.length>1?!r.filter((function(t){return!(e.length>e.filter((function(e){return!U(e)(t)})).length)})).length:e.length>e.filter((function(t){return!V(r,t)})).length};function Y(t,e){return function(r){return t(e(r))}}var G=Y(Object.getPrototypeOf,Object),K=Function.prototype,Q=Object.prototype,X=K.toString,Z=Q.hasOwnProperty,tt=X.call(Object);function et(t){if(!v(t)||"[object Object]"!=h(t))return!1;var e=G(t);if(null===e)return!0;var r=Z.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&X.call(r)==tt}var rt,nt=function(t,e,r){for(var n=-1,o=Object(t),u=r(t),i=u.length;i--;){var a=u[rt?i:++n];if(!1===e(o[a],a,o))break}return t};function ot(t){return v(t)&&"[object Arguments]"==h(t)}var ut=Object.prototype,it=ut.hasOwnProperty,at=ut.propertyIsEnumerable,ct=ot(function(){return arguments}())?ot:function(t){return v(t)&&it.call(t,"callee")&&!at.call(t,"callee")};var ft="object"==typeof exports&&exports&&!exports.nodeType&&exports,st=ft&&"object"==typeof module&&module&&!module.nodeType&&module,lt=st&&st.exports===ft?n.Buffer:void 0,pt=(lt?lt.isBuffer:void 0)||function(){return!1},ht=/^(?:0|[1-9]\d*)$/;function vt(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&ht.test(t))&&t>-1&&t%1==0&&t-1&&t%1==0&&t<=9007199254740991}var dt={};dt["[object Float32Array]"]=dt["[object Float64Array]"]=dt["[object Int8Array]"]=dt["[object Int16Array]"]=dt["[object Int32Array]"]=dt["[object Uint8Array]"]=dt["[object Uint8ClampedArray]"]=dt["[object Uint16Array]"]=dt["[object Uint32Array]"]=!0,dt["[object Arguments]"]=dt["[object Array]"]=dt["[object ArrayBuffer]"]=dt["[object Boolean]"]=dt["[object DataView]"]=dt["[object Date]"]=dt["[object Error]"]=dt["[object Function]"]=dt["[object Map]"]=dt["[object Number]"]=dt["[object Object]"]=dt["[object RegExp]"]=dt["[object Set]"]=dt["[object String]"]=dt["[object WeakMap]"]=!1;var yt,bt="object"==typeof exports&&exports&&!exports.nodeType&&exports,_t=bt&&"object"==typeof module&&module&&!module.nodeType&&module,mt=_t&&_t.exports===bt&&e.process,jt=function(){try{var t=_t&&_t.require&&_t.require("util").types;return t||mt&&mt.binding&&mt.binding("util")}catch(t){}}(),wt=jt&&jt.isTypedArray,St=wt?(yt=wt,function(t){return yt(t)}):function(t){return v(t)&>(t.length)&&!!dt[h(t)]},Ot=Object.prototype.hasOwnProperty;function kt(t,e){var r=i(t),n=!r&&ct(t),o=!r&&!n&&pt(t),u=!r&&!n&&!o&&St(t),a=r||n||o||u,c=a?function(t,e){for(var r=-1,n=Array(t);++r-1},Ft.prototype.set=function(t,e){var r=this.__data__,n=Rt(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};var Lt,Wt=n["__core-js_shared__"],Jt=(Lt=/[^.]+$/.exec(Wt&&Wt.keys&&Wt.keys.IE_PROTO||""))?"Symbol(src)_1."+Lt:"";var It=Function.prototype.toString;function Dt(t){if(null!=t){try{return It.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var Ut=/^\[object .+?Constructor\]$/,Vt=Function.prototype,Bt=Object.prototype,Ht=Vt.toString,Yt=Bt.hasOwnProperty,Gt=RegExp("^"+Ht.call(Yt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function Kt(t){return!(!Pt(t)||function(t){return!!Jt&&Jt in t}(t))&&(qt(t)?Gt:Ut).test(Dt(t))}function Qt(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return Kt(r)?r:void 0}var Xt=Qt(n,"Map"),Zt=Qt(Object,"create");var te=Object.prototype.hasOwnProperty;var ee=Object.prototype.hasOwnProperty;function re(t){var e=-1,r=null==t?0:t.length;for(this.clear();++ea))return!1;var f=u.get(t);if(f&&u.get(e))return f==e;var s=-1,l=!0,p=2&r?new ie:void 0;for(u.set(t,e),u.set(e,t);++se.type.filter((function(t){var e;return void 0===r||(!1!==(e=B(t))?!H({arg:r},e):!U(t)(r))})).length)})).length}return!1},rr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 406},r.name.get=function(){return"Jsonql406Error"},Object.defineProperties(e,r),e}(Error),nr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"Jsonql500Error"},Object.defineProperties(e,r),e}(Error),or=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 403},r.name.get=function(){return"JsonqlForbiddenError"},Object.defineProperties(e,r),e}(Error),ur=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlAuthorisationError"},Object.defineProperties(e,r),e}(Error),ir=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlContractAuthError"},Object.defineProperties(e,r),e}(Error),ar=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"JsonqlResolverAppError"},Object.defineProperties(e,r),e}(Error),cr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 404},r.name.get=function(){return"JsonqlResolverNotFoundError"},Object.defineProperties(e,r),e}(Error),fr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlEnumError"},Object.defineProperties(e,r),e}(Error),sr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlTypeError"},Object.defineProperties(e,r),e}(Error),lr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlCheckerError"},Object.defineProperties(e,r),e}(Error),pr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(e,r),e}(Error),hr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0},statusCode:{configurable:!0}};return r.name.get=function(){return"JsonqlError"},r.statusCode.get=function(){return-1},Object.defineProperties(e,r),e}(Error),vr=function(t){function e(r,n){t.call(this,n),this.statusCode=r,this.className=e.name}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlServerError"},Object.defineProperties(e,r),e}(Error);function gr(t){if(Array.isArray(t))throw new pr("",t);var e=t.message||"No message",r=t.detail||t;switch(!0){case t instanceof rr:throw new rr(e,r);case t instanceof nr:throw new nr(e,r);case t instanceof or:throw new or(e,r);case t instanceof ur:throw new ur(e,r);case t instanceof ir:throw new ir(e,r);case t instanceof ar:throw new ar(e,r);case t instanceof cr:throw new cr(e,r);case t instanceof fr:throw new fr(e,r);case t instanceof sr:throw new sr(e,r);case t instanceof lr:throw new lr(e,r);case t instanceof pr:throw new pr(e,r);case t instanceof vr:throw new vr(e,r);default:throw new hr(e,r)}}var dr=function(t,e){var r,n,o,u,i;switch(!0){case"object"===t:return o=(n=e).arg,u=n.param,i=[o],Array.isArray(u.keys)&&u.keys.length&&i.push(u.keys),!Reflect.apply(er,null,i);case"array"===t:return!V(e.arg);case!1!==(r=B(t)):return!H(e,r);default:return!U(t)(e.arg)}},yr=function(t,e){return void 0!==t?t:!0===e.optional&&void 0!==e.defaultvalue?e.defaultvalue:null},br=function(t,e,r){var n;void 0===r&&(r=!1);var o=function(t,e){if(!V(e))throw new hr("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===e.length)return[];if(!V(t))throw new hr("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==e.length:return t.map((function(t,r){return{arg:t,index:r,param:e[r]}}));case!0===e[0].variable:var r=e[0].type;return t.map((function(t,n){return{arg:t,index:n,param:e[n]||{type:r,name:"_"}}}));case t.lengthe.length:var n=e.length,o=["any"];return t.map((function(t,r){var u=r>=n||!!e[r].optional,i=e[r]||{type:o,name:"_"+r};return{arg:u?yr(t,i):t,index:r,param:i,optional:u}}));default:throw new hr("Could not understand your arguments and parameter structure!",{args:t,params:e})}}(t,e),u=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var e=t.arg,r=t.param;return!!M(e)&&!(r.type.length>r.type.filter((function(e){return dr(e,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(e){return dr(e,t)})).length)}));return r?((n={}).error=u,n.data=o.map((function(t){return t.arg})),n):u},_r=function(){try{var t=Qt(Object,"defineProperty");return t({},"",{}),t}catch(t){}}();function mr(t,e,r){"__proto__"==e&&_r?_r(t,e,{configurable:!0,enumerable:!0,value:r,writable:!0}):t[e]=r}function jr(t,e,r){(void 0===r||Ct(t[e],r))&&(void 0!==r||e in t)||mr(t,e,r)}var wr="object"==typeof exports&&exports&&!exports.nodeType&&exports,Sr=wr&&"object"==typeof module&&module&&!module.nodeType&&module,Or=Sr&&Sr.exports===wr?n.Buffer:void 0,kr=Or?Or.allocUnsafe:void 0;function Er(t,e){var r,n,o=e?(r=t.buffer,n=new r.constructor(r.byteLength),new fe(n).set(new fe(r)),n):t.buffer;return new t.constructor(o,t.byteOffset,t.length)}var $r=Object.create,Tr=function(){function t(){}return function(e){if(!Pt(e))return{};if($r)return $r(e);t.prototype=e;var r=new t;return t.prototype=void 0,r}}();function Ar(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var Pr=Object.prototype.hasOwnProperty;function qr(t,e,r){var n=t[e];Pr.call(t,e)&&Ct(n,r)&&(void 0!==r||e in t)||mr(t,e,r)}var zr=Object.prototype.hasOwnProperty;function Nr(t){if(!Pt(t))return function(t){var e=[];if(null!=t)for(var r in Object(t))e.push(r);return e}(t);var e=$t(t),r=[];for(var n in t)("constructor"!=n||!e&&zr.call(t,n))&&r.push(n);return r}function xr(t){return zt(t)?kt(t,!0):Nr(t)}function Cr(t){return function(t,e,r,n){var o=!r;r||(r={});for(var u=-1,i=e.length;++u0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(Wr);function Dr(t,e){return Ir(function(t,e,r){return e=Lr(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,u=Lr(n.length-e,0),i=Array(u);++o1?e[n-1]:void 0,u=n>2?e[2]:void 0;for(o=Ur.length>3&&"function"==typeof o?(n--,o):void 0,u&&function(t,e,r){if(!Pt(r))return!1;var n=typeof e;return!!("number"==n?zt(r)&&vt(e,r.length):"string"==n&&e in r)&&Ct(r[e],t)}(e[0],e[1],u)&&(o=n<3?void 0:o,n=1),t=Object(t);++r0?Array.from(this.queueStore):[]},hn.prototype.release=function(){var t=this,e=this.queueStore.size;if(this.logger("(release)","Release was called "+e),e>0){var r=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",r),r.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(hn.prototype,vn);var gn=function(t){function e(e){if("function"!=typeof e)throw new Error("Just die here the logger is not a function!");t.call(this,{logger:e})}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(e.prototype,r),e}(function(t){function e(e){void 0===e&&(e={}),t.call(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={$done:{configurable:!0}};return e.prototype.logger=function(){},e.prototype.$on=function(t,e,r){var n=this;void 0===r&&(r=null);this.validate(t,e);var o=this.takeFromStore(t);if(!1===o)return this.logger("($on)",t+" callback is not in lazy store"),this.addToNormalStore(t,"on",e,r);this.logger("($on)",t+" found in lazy store");var u=0;return o.forEach((function(o){var i=o[0],a=o[1],c=o[2];if(c&&"on"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);n.logger("($on)","call run on "+t),n.run(e,i,r||a),u+=n.addToNormalStore(t,"on",e,r||a)})),u},e.prototype.$once=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=this.takeFromStore(t);this.normalStore;if(!1===n)return this.logger("($once)",t+" not in the lazy store"),this.addToNormalStore(t,"once",e,r);this.logger("($once)",n);var o=Array.from(n)[0],u=o[0],i=o[1],a=o[2];if(a&&"once"!==a)throw new Error("You are trying to register an event already been taken by other type: "+a);this.logger("($once)","call run for "+t),this.run(e,u,r||i),this.$off(t)},e.prototype.$only=function(t,e,r){var n=this;void 0===r&&(r=null),this.validate(t,e);var o=!1,u=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger("($only)",t+" add to store"),o=this.addToNormalStore(t,"only",e,r)),!1!==u)&&(this.logger("($only)",t+" found data in lazy store to execute"),Array.from(u).forEach((function(o){var u=o[0],i=o[1],a=o[2];if(a&&"only"!==a)throw new Error("You are trying to register an event already been taken by other type: "+a);n.logger("($only)","call run for "+t),n.run(e,u,r||i)})));return o},e.prototype.$onlyOnce=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=!1,o=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger("($onlyOnce)",t+" add to store"),n=this.addToNormalStore(t,"onlyOnce",e,r)),!1!==o){this.logger("($onlyOnce)",o);var u=Array.from(o)[0],i=u[0],a=u[1],c=u[2];if(c&&"onlyOnce"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);this.logger("($onlyOnce)","call run for "+t),this.run(e,i,r||a),this.$off(t)}return n},e.prototype.$replace=function(t,e,r,n){if(void 0===r&&(r=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,e),Reflect.apply(o,this,[t,e,r])}throw new Error(n+" is not supported!")},e.prototype.$trigger=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,u=this.normalStore;if(this.logger("($trigger)","normalStore",u),u.has(t)){var i=this.$queue(t,e,r,n);if(this.logger("($trigger)",t,"found; add to queue: ",i),!0===i)return this.logger("($trigger)",t,"not executed. Exit now."),!1;for(var a=Array.from(u.get(t)),c=a.length,f=!1,s=0;s0;)n[o]=arguments[o+2];if(t.has(e)?(this.logger("(addToStore)",e+" existed"),r=t.get(e)):(this.logger("(addToStore)","create new Set for "+e),r=new Set),n.length>2)if(Array.isArray(n[0])){var u=n[2];this.checkTypeInLazyStore(e,u)||r.add(n)}else this.checkContentExist(n,r)||(this.logger("(addToStore)","insert new",n),r.add(n));else r.add(n);return t.set(e,r),[t,r.size]},e.prototype.checkContentExist=function(t,e){return!!Array.from(e).filter((function(e){return e[0]===t[0]})).length},e.prototype.checkTypeInStore=function(t,e){this.validateEvt(t,e);var r=this.$get(t,!0);return!1===r||!r.filter((function(t){var r=t[3];return e!==r})).length},e.prototype.checkTypeInLazyStore=function(t,e){this.validateEvt(t,e);var r=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",r),!!r&&!!Array.from(r).filter((function(t){return t[2]!==e})).length},e.prototype.addToNormalStore=function(t,e,r,n){if(void 0===n&&(n=null),this.logger("(addToNormalStore)",t,e,"try to add to normal store"),this.checkTypeInStore(t,e)){this.logger("(addToNormalStore)",e+" can add to "+t+" normal store");var o=this.hashFnToKey(r),u=[this.normalStore,t,o,r,n,e],i=Reflect.apply(this.addToStore,this,u),a=i[0],c=i[1];return this.normalStore=a,c}return!1},e.prototype.addToLazyStore=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(e),r];n&&o.push(n);var u=Reflect.apply(this.addToStore,this,o),i=u[0],a=u[1];return this.lazyStore=i,a},e.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},r.normalStore.set=function(t){ln.set(this,t)},r.normalStore.get=function(){return ln.get(this)},r.lazyStore.set=function(t){pn.set(this,t)},r.lazyStore.get=function(){return pn.get(this)},e.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,e){return(t=(t<<5)-t+e.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(e.prototype,r),e}(hn))),dn=function(t){var e=t.log,r=t.eventEmitter;return r?(e("eventEmitter is:",r.name),r):(e("Create a new Event Emitter"),new gn(t.log))},yn=function(t){return i(t)?t:[t]},bn=function(t,e){try{var r=Object.keys(t);return n=e,!!r.filter((function(t){return t===n})).length}catch(t){return!1}var n},_n=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return t.join("_")},mn=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},jn=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return Reflect.apply(e,null,yn(t))}),Reflect.apply(t,null,r))}};function wn(t,e,r,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,e)&&Object.defineProperty(t,e,{set:r,get:null===n?function(){return null}:n}),t}function Sn(t,e,r,n){void 0===n&&(n=!1);var o=function(t,e){var r=Object.getOwnPropertyDescriptor(t,e);return void 0!==r&&r.value?r.value:r}(t,e);return!1===n&&void 0!==o||Object.defineProperty(t,e,{value:r,writable:n}),t}function On(t){return!!bn(t,"socket")&&t.socket}function kn(t){var e,r,n=t.contract;return t.enableAuth?function(t,e){void 0===e&&(e=!1);var r=On(t);if(!1===r){if(e)return t;throw new hr("socket not found in contract!")}var n,o={},u=0;for(var i in r){var a=r[i],c=a.namespace;c&&(o[c]||(++u,o[c]={}),o[c][i]=a,n||a.public&&(n=c))}return{size:u,nspSet:o,publicNamespace:n}}(n):((r={}).nspSet=((e={}).jsonql=function(t){var e=On(t);if(!1!==e)return e;throw new cr("Missing property in contract!")}(n),e),r.publicNamespace="jsonql",r)}var En=function(t,e,r){return[Sn(t,e.loginHandlerName,(function(t){if(t&&on(t))return r.$trigger("__login__",[t]);throw new pr(e.loginHandlerName,"Unexpected token "+t)})),r,e]},$n=function(t,e,r){return[Sn(t,e.logoutHandlerName,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__logout__",t)})),r]};function Tn(t,e){return objDefineProps(t,"onLogin",(function(t){isFunc(t)&&e.$only("onLogin",t)}))}function An(t,e,r){return jn(En,$n,Tn)(t,e,r)}function Pn(t,e,r){bn(t,"error")?r(t.error):bn(t,"data")?e(t.data):r({message:"UKNNOWN RESULT!",error:t})}function qn(t,e,r,n){void 0===n&&(n=[]);var o=_n(e,"emit");return debugFn("actionCall: "+o+" --\x3e "+r,n),t.$trigger(o,[r,yn(n)]),new Promise((function(n,o){t.$on(_n(e,r,"onResult"),(function(t){debugFn("got the first result",t),Pn(t,n,o)}))}))}var zn,Nn,xn=function(t,e,r,n,o){return wn(t,"send",(function(t){un(yn(t),o.params,!0).then((function(o){if(!o.error||!o.error.length)return qn(e,r,n,t);e.$call(_n(r,n,"onError"),[new pr(n,o.error)])})).catch((function(t){e.$call(_n(r,n,"onError"),[new pr(n,t)])}))}),(function(){return function(){for(var t=[],u=arguments.length;u--;)t[u]=arguments[u];return un(t,o.params,!0).then((function(t){return qn(e,r,n,t)})).catch(gr)}}))},Cn=function(t,e,r,n,o){return[Sn(t,"myNamespace",r),e,r,n,o]},Rn=function(t,e,r,n,o){return[wn(t,"onResult",(function(t){mn(t)&&e.$on(_n(r,n,"onResult"),(function(o){Pn(o,t,(function(t){e.$trigger(_n(r,n,"onError"),t)}))}))})),e,r,n,o]},Mn=function(t,e,r,n,o){return[wn(t,"onMessage",(function(t){if(mn(t)){e.$only(_n(r,n,"onMessage"),(function(o){Pn(o,t,(function(t){e.$trigger(_n(r,n,"onError"),t)}))}))}})),e,r,n,o]},Fn=function(t,e,r,n,o){return[wn(t,"onError",(function(t){mn(t)&&e.$only(_n(r,n,"onError"),t)})),e,r,n,o]};function Ln(t,e,r,n,o){var u=[Cn];u.push(Rn,Mn,Fn),u.push(xn);var i=Reflect.apply(jn,null,u);return Reflect.apply(i,null,[n,o,t,e,r])}function Wn(t,e,r,n){return function(){for(var o=[],u=arguments.length;u--;)o[u]=arguments[u];return un(o,n.params,!0).then((function(n){return qn(t,e,r,n)})).catch(gr)}}function Jn(t,e,r){var n={};for(var o in r){var u=r[o];for(var i in u){var a=u[i];n=Sn(n,i,Ln(o,i,a,Wn(e,o,i,a),e))}}return[n,t,e,r]}function In(t,e,r,n){return[wn(t,"onError",(function(t){if(mn(t))for(var e in n)r.$on(_n(e,"onError"),t)})),e,r]}function Dn(t,e,r){return[wn(t,"onReady",(function(t){mn(t)&&r.$on("onReady",t)})),e,r]}var Un=["roundtip","handshake"],Vn={loginHandlerName:an("login",["string"]),logoutHandlerName:an("logout",["string"]),loginMethod:an("handshake",["string"],(zn={},zn.enumv=Un,zn)),useJwt:an(!0,["boolean","string"]),authStrKey:an(null,["string"]),hostname:an(!1,["string"]),namespace:an("jsonql",["string"]),wsOptions:an({},["object"]),contract:an({},["object"],(Nn={},Nn.checker=function(t){return!!function(t){return et(t)&&(bn(t,"query")||bn(t,"mutation")||bn(t,"socket"))}(t)&&t},Nn)),enableAuth:an(!1,["boolean"]),token:an(!1,["string"])},Bn={eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:""};function Hn(t){return Promise.resolve(t).then((function(t){var e;return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new pr(t)}}()),t.wssPath=(e=[t.hostname,t.namespace].join("/"),"ws"===t.serverType?e.replace("http://","ws://"):e),t}))}function Yn(t,e,r){return function(t,e,r){var n=Object.assign(Bn,r),o=Object.assign(Vn,e);return cn(t,o,n)}(t,e,r).then(Hn)}function Gn(t,e){return Promise.resolve(e).then(sn).then((function(t){return{opts:t,nspMap:kn(t),ee:dn(t)}})).then((function(e){var r=e.opts,n=e.nspMap,o=e.ee;return t(r,n,o)})).then((function(t){return function(t,e,r){var n=e.nspSet,o=[Jn,In,Dn];return t.enableAuth?o.push(An):o.push((function(t){return t})),Reflect.apply(jn,null,o)(t,r,n)}(t.opts,t.nspMap,t.ee)})).catch((function(t){console.error("jsonql-ws-core-client init error",t)}))}var Kn=null;"undefined"!=typeof WebSocket?Kn=WebSocket:"undefined"!=typeof MozWebSocket?Kn=MozWebSocket:void 0!==t?Kn=t.WebSocket||t.MozWebSocket:"undefined"!=typeof window?Kn=window.WebSocket||window.MozWebSocket:"undefined"!=typeof self&&(Kn=self.WebSocket||self.MozWebSocket);var Qn=Kn,Xn=function(t){var e=t.toLowerCase();return e.indexOf("http")>-1?e.indexOf("https")>-1?e.replace("https","wss"):e.replace("http","ws"):e};function Zn(t,e){return void 0===e&&(e=!1),!1===e?function(e){return new t(Xn(e))}:function(e,r){var n=Xn(e),o=r&&"string"==typeof r?n+"?token="+r:n;try{return new t(o)}catch(t){return console.error("WebSocket Connection Error",t),!1}}}var to=Array.isArray,eo="object"==typeof t&&t&&t.Object===Object&&t,ro="object"==typeof self&&self&&self.Object===Object&&self,no=(eo||ro||Function("return this")()).Symbol,oo=Object.prototype,uo=oo.hasOwnProperty,io=oo.toString,ao=no?no.toStringTag:void 0;var co=Object.prototype.toString;var fo=no?no.toStringTag:void 0;function so(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":fo&&fo in Object(t)?function(t){var e=uo.call(t,ao),r=t[ao];try{t[ao]=void 0;var n=!0}catch(t){}var o=io.call(t);return n&&(e?t[ao]=r:delete t[ao]),o}(t):function(t){return co.call(t)}(t)}function lo(t){return null!=t&&"object"==typeof t}var po=no?no.prototype:void 0,ho=po?po.toString:void 0;function vo(t){if("string"==typeof t)return t;if(to(t))return function(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var u=Array(o);++n-1;);return r}(o,u),function(t,e){for(var r=t.length;r--&&bo(e,t[r],0)>-1;);return r}(o,u)+1).join("")}var No=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return t.join("_")},xo=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(e,r),e}(Error),Co=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0},statusCode:{configurable:!0}};return r.name.get=function(){return"JsonqlError"},r.statusCode.get=function(){return-1},Object.defineProperties(e,r),e}(Error);var Ro=function(t){void 0===t&&(t=!1);var e=Date.now();return t?Math.floor(e/1e3):e};function Mo(t){return"string"==typeof t||!to(t)&&lo(t)&&"[object String]"==so(t)}function Fo(t,e,r){if(void 0===e&&(e=[]),void 0===r&&(r=!1),Mo(t)&&to(e)){var n=function(t){var e;return(e={}).args=t,e}(e);return!0===r?n:function(t,e){var r;return(r={})[t]=e,r.TS=[Ro()],r}(t,n)}throw new xo("[createQuery] expect resolverName to be string and args to be array!",{resolverName:t,args:e})}function Lo(t,e){var r=e.hostname,n=e.wssPath,o=e.wsOptions;return(0,e.nspClient)(t?[r,t].join("/"):n,o)}var Wo=function(t){return""!==zo(t)&&Mo(t)},Jo=function(){this.__suspend__=null,this.queueStore=new Set},Io={$suspend:{configurable:!0},$queues:{configurable:!0}};Io.$suspend.set=function(t){var e=this;if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value!");var r=this.__suspend__;this.__suspend__=t,this.logger("($suspend)","Change from "+r+" --\x3e "+t),!0===r&&!1===t&&setTimeout((function(){e.release()}),1)},Jo.prototype.$queue=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return!0===this.__suspend__&&(this.logger("($queue)","added to $queue",t),this.queueStore.add(t)),this.__suspend__},Io.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},Jo.prototype.release=function(){var t=this,e=this.queueStore.size;if(this.logger("(release)","Release was called "+e),e>0){var r=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",r),r.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(Jo.prototype,Io);var Do=function(t,e){var r;(to(r=e)?r:[r]).forEach((function(e){t.$off(No(e,"emit"))}))};var Uo=function(t,e,r){var n=r.useCallbackStyle,o=r.log,u=n?"error":"onError",i=n?"result":"onResult";e.$only(No(t,"emit"),(function(r,n){o("[notLoginHandler] hijack the ws call",t,r,n);var a={message:"NOT LOGIN"};e.$call(No(t,r,u),[a]),e.$call(No(t,r,i),[{error:a}])}))};function Vo(t,e,r,n,o,u){var i=function(t){return t.length>1&&t[0]}(o),a=!1,c=t.log;o.forEach((function(o){if(a=i===o,u[o]){c("[call bindWsHandler]",a,o);var f=[o,u[o],r,a,t];if("socket.io"===t.serverType){var s=e.nspSet;f.push(s[o])}Reflect.apply(n,null,f)}else Uo(o,r,t)})),r.$on("__logout__",(function(){c("LOGOUT_EVENT_NAME"),function(t,e,r,n){void 0===n&&(n={});var o=n.useCallbackStyle?"error":"onError";e.forEach((function(e){t.$call(No(e,o),[{message:r,namespace:e}])}))}(r,o,"__logout__"),o.forEach((function(e){Do(r,e),u[e]=!1,Uo(e,r,t)}))}))}var Bo=["__reply__","__event__","__data__"],Ho=function(t){var e=t.data;return!!e&&(Bo.filter((function(t){return function(t,e){try{var r=Object.keys(t);return n=e,!!r.filter((function(t){return t===n})).length}catch(t){return!1}var n}(e,t)})).length===Bo.length&&e)},Yo=function(t,e,r,n,o){var u=[e];r&&u.push(r),u.push(o);var i=Reflect.apply(No,null,u),a=n.data||n;t.$trigger(i,[a])};function Go(t,e,r,n,o){var u=o.useCallbackStyle,i=o.log;i("wsMainHandler log test");var a=u?"ready":"onReady",c=u?"login":"onLogin",f=u?"message":"onMessage",s=u?"result":"onResult",l=u?"error":"onError";e.onopen=function(){i("ws.onopen listened"),r.$call(a,t),n&&(i("isPrivate and fire the "+c),r.$call(c,t)),r.$only(No(t,"emit"),(function(t,r){i("calling server",t,r),e.send(function(t,e,r){return void 0===e&&(e=[]),void 0===r&&(r=!1),JSON.stringify(Fo(t,e,r))}(t,r))}))},e.onmessage=function(e){try{var n=function(t){var e,r=t.data,n=Wo(r)?JSON.parse(r):r;if(!1!==(e=Ho(n)))return{resolverName:e.__event__,data:e.__data__,type:e.__reply__};throw new Co("payload can not be decoded",t)}(e),o=n.resolverName,u=n.type;switch(i("Hear from server",u,n),u){case"emit":var a=No(t,o,f),c=r.$trigger(a,[n]);i("EMIT_REPLY_TYPE",a,c);break;case"acknowledge":var p=No(t,o,s);r.$trigger(p,[n]);break;case"error":i("ERROR_TYPE"),Yo(r,t,o,n,l);break;default:i("Unhandled event!",n),Yo(r,t,o,n,l)}}catch(e){console.error("ws.onmessage error",e),Yo(r,t,!1,e,l)}},e.onclose=function(){i("ws.onclose callback")},r.$on("__logout__",(function(){try{i("terminate ws connection"),e.terminate()}catch(t){console.error("ws.terminate error",t)}}))}var Ko=function(t,e,r){var n,o=e.nspSet,u=e.publicNamespace,i=!1,a=[],c={};if(t.enableAuth)i=!0,c=(a=function(t,e){var r=[];for(var n in t)n===e?r[1]=n:r[0]=n;return r}(o,u)).map((function(e,n){var o,u,i;return 0===n?r?(t.token=r,(o={})[e]=function(t,e){var r=e.hostname,n=e.wssPath,o=e.token,u=e.wsOptions,i=e.nspAuthClient,a=t?[r,t].join("/"):n;if(o&&"string"!=typeof o)throw new Error("Expect token to be string, but got "+o);return i(a,o,u)}(e,t),o):((u={})[e]=!1,u):((i={})[e]=Lo(e,t),i)})).reduce((function(t,e){return Object.assign(t,e)}),{});else{var f=(n=o,Object.keys(n)[0]);a.push(f),c[f]=Lo(!1,t)}return{nsps:c,namespaces:a,login:i}};var Qo=function(t){var e=Zn(t),r=Zn(t,!0);return function(t,n,o){t.nspClient=e,t.nspAuthClient=r;var u=t.log;return u&&"function"==typeof u&&(u("@jsonql/ws ee",o.name),u("@jsonql/ws createClientResolver",t)),function(t,e,r){var n=[t,e,r,Go],o=t.token,u=t.log,i=Ko(t,e,o),a=i.nsps,c=i.namespaces,f=i.login;return Reflect.apply(Vo,null,n.concat([c,a])),f&&r.$only("__login__",(function(o){u("createClient LOGIN_EVENT_NAME"),Do(r,c);var i=Ko(t,e,o);Reflect.apply(Vo,null,n.concat([i.namespaces,i.nsps]))})),{opts:t,nspMap:e,ee:r}}(t,n,o)}}(Qn),Xo={version:"version: 1.1.0 module: umd",serverType:"ws"},Zo={};return function(t,e){return void 0===t&&(t={}),void 0===e&&(e={}),function(t,e,r){return void 0===e&&(e={}),void 0===r&&(r={}),function(n){return void 0===n&&(n={}),Yn(n,e,r).then((function(e){return Gn(t,e)}))}}(Qo,Zo,Object.assign(Xo,e))(t)}})); //# sourceMappingURL=jsonql-ws-client.umd.js.map diff --git a/packages/@jsonql/ws/main.js b/packages/@jsonql/ws/main.js index 8b447e30..c3cf670b 100644 --- a/packages/@jsonql/ws/main.js +++ b/packages/@jsonql/ws/main.js @@ -1,8031 +1,2 @@ -'use strict'; - -function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } - -var WebSocket = _interopDefault(require('ws')); - -/** - * 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? - */ -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; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, Jsonql406Error); - } - } - - 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 406; - }; - - staticAccessors.name.get = function () { - return 'Jsonql406Error'; - }; - - Object.defineProperties( Jsonql406Error, staticAccessors ); - - return Jsonql406Error; -}(Error)); - -/** - * 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? - */ -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; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, Jsonql500Error); - } - } - - 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 500; - }; - - staticAccessors.name.get = function () { - return 'Jsonql500Error'; - }; - - Object.defineProperties( Jsonql500Error, staticAccessors ); - - return Jsonql500Error; -}(Error)); - -/** - * 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? - */ -var JsonqlForbiddenError = /*@__PURE__*/(function (Error) { - function JsonqlForbiddenError() { - 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 = JsonqlForbiddenError.name; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlForbiddenError); - } - } - - if ( Error ) JsonqlForbiddenError.__proto__ = Error; - JsonqlForbiddenError.prototype = Object.create( Error && Error.prototype ); - JsonqlForbiddenError.prototype.constructor = JsonqlForbiddenError; - - var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; - - staticAccessors.statusCode.get = function () { - return 403; - }; - - staticAccessors.name.get = function () { - return 'JsonqlForbiddenError'; - }; - - Object.defineProperties( JsonqlForbiddenError, staticAccessors ); - - return JsonqlForbiddenError; -}(Error)); - -/** - * 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? - */ -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); - } - } - - 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 401; - }; - - staticAccessors.name.get = function () { - return 'JsonqlAuthorisationError'; - }; - - Object.defineProperties( JsonqlAuthorisationError, staticAccessors ); - - return JsonqlAuthorisationError; -}(Error)); - -/** - * 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? - */ -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]; - - this.className = JsonqlContractAuthError.name; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlContractAuthError); - } - } - - 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 401; - }; - - staticAccessors.name.get = function () { - return 'JsonqlContractAuthError'; - }; - - Object.defineProperties( JsonqlContractAuthError, staticAccessors ); - - return JsonqlContractAuthError; -}(Error)); - -/** - * 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? - */ -var JsonqlResolverAppError = /*@__PURE__*/(function (Error) { - function JsonqlResolverAppError() { - 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 = JsonqlResolverAppError.name; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlResolverAppError); - } - } - - 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 500; - }; - - staticAccessors.name.get = function () { - return 'JsonqlResolverAppError'; - }; - - Object.defineProperties( JsonqlResolverAppError, staticAccessors ); - - return JsonqlResolverAppError; -}(Error)); - -/** - * 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? - */ -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; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlResolverNotFoundError); - } - } - - 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 404; - }; - - staticAccessors.name.get = function () { - return 'JsonqlResolverNotFoundError'; - }; - - Object.defineProperties( JsonqlResolverNotFoundError, staticAccessors ); - - return JsonqlResolverNotFoundError; -}(Error)); - -// 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); - } - } - - 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 ( 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 ( 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)); - -// 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); - - this.message = args[0]; - this.detail = args[1]; - - this.className = JsonqlValidationError.name; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlValidationError); - } - } - - if ( Error ) JsonqlValidationError.__proto__ = Error; - JsonqlValidationError.prototype = Object.create( Error && Error.prototype ); - JsonqlValidationError.prototype.constructor = JsonqlValidationError; - - var staticAccessors = { name: { configurable: true } }; - - staticAccessors.name.get = function () { - return 'JsonqlValidationError'; - }; - - Object.defineProperties( JsonqlValidationError, staticAccessors ); - - return JsonqlValidationError; -}(Error)); - -// 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 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 CHECKED_KEY = '__checked__'; -var LOGIN_NAME = 'login'; -var ISSUER_NAME = LOGIN_NAME; // legacy issue need to replace them later -var LOGOUT_NAME = 'logout'; - -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 = '>'; - -var NO_ERROR_MSG = 'No message'; -var NO_STATUS_CODE = -1; -var LOGIN_EVENT_NAME = '__login__'; -var LOGOUT_EVENT_NAME = '__logout__'; - -// for ws servers -var WS_REPLY_TYPE = '__reply__'; -var WS_EVT_NAME = '__event__'; -var WS_DATA_NAME = '__data__'; -var EMIT_REPLY_TYPE = 'emit'; -var ACKNOWLEDGE_REPLY_TYPE = 'acknowledge'; -var ERROR_TYPE = 'error'; - -var NSP_SET = 'nspSet'; -var PUBLIC_NAMESPACE = 'publicNamespace'; - -var JS_WS_SOCKET_IO_NAME = 'socket.io'; -var JS_WS_NAME = 'ws'; - -// for ws client -var ON_MESSAGE_PROP_NAME = 'onMessage'; -var ON_RESULT_PROP_NAME = 'onResult'; -var ON_ERROR_PROP_NAME = 'onError'; -var ON_READY_PROP_NAME = 'onReady'; -var ON_LOGIN_PROP_NAME = 'onLogin'; // new @1.8.6 - -var SEND_MSG_PROP_NAME = 'send'; -// breaking change from 1.8.8 the above name was the name below -// the names are using in the new resolver.on getter interface -var MESSAGE_PROP_NAME = 'message'; -var RESULT_PROP_NAME = 'result'; -var ERROR_PROP_NAME = 'error'; -var READY_PROP_NAME = 'ready'; -var LOGIN_PROP_NAME = 'login'; // new @1.8.6 -var NOT_LOGIN_ERR_MSG = 'NOT LOGIN'; -var TOKEN_PARAM_NAME = 'token'; -var IO_ROUNDTRIP_LOGIN = 'roundtip'; -var IO_HANDSHAKE_LOGIN = 'handshake'; - -/** - * 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 = /*@__PURE__*/(function (Error) { - function JsonqlError() { - 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 = JsonqlError.name; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, JsonqlError); - // this.detail = this.stack; - } - } - - if ( Error ) JsonqlError.__proto__ = Error; - JsonqlError.prototype = Object.create( Error && Error.prototype ); - JsonqlError.prototype.constructor = JsonqlError; - - var staticAccessors = { name: { configurable: true },statusCode: { configurable: true } }; - - staticAccessors.name.get = function () { - return 'JsonqlError'; - }; - - staticAccessors.statusCode.get = function () { - return NO_STATUS_CODE; - }; - - Object.defineProperties( JsonqlError, staticAccessors ); - - return JsonqlError; -}(Error)); - -// 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; - } - - if ( Error ) JsonqlServerError.__proto__ = Error; - JsonqlServerError.prototype = Object.create( Error && Error.prototype ); - JsonqlServerError.prototype.constructor = JsonqlServerError; - - var staticAccessors = { name: { configurable: true } }; - - staticAccessors.name.get = function () { - return 'JsonqlServerError'; - }; - - 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 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(msg, detail) - } -} - -// constants - -var SOCKET_IO = JS_WS_SOCKET_IO_NAME; - -var MISSING_PROP_ERR = 'Missing property in contract!'; - -var EMIT_EVT = EMIT_REPLY_TYPE; - -var UNKNOWN_RESULT = 'UKNNOWN RESULT!'; - -var MY_NAMESPACE = 'myNamespace'; - -var CB_FN_NAME = 'on'; - -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; - -/** - * 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; -} - -/** - * 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 = Array.isArray; - -/** Used for built-in method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; - -/** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ -var nativeObjectToString = objectProto.toString; - -/** Built-in value references. */ -var symToStringTag = Symbol ? Symbol.toStringTag : undefined; - -/** - * 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(value) { - var isOwn = hasOwnProperty.call(value, symToStringTag), - tag = value[symToStringTag]; - - try { - value[symToStringTag] = undefined; - var unmasked = true; - } catch (e) {} - - var result = nativeObjectToString.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag] = tag; - } else { - delete value[symToStringTag]; - } - } - return result; -} - -/** Used for built-in method references. */ -var objectProto$1 = Object.prototype; - -/** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ -var nativeObjectToString$1 = objectProto$1.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(value) { - return nativeObjectToString$1.call(value); -} - -/** `Object#toString` result references. */ -var nullTag = '[object Null]', - undefinedTag = '[object Undefined]'; - -/** Built-in value references. */ -var symToStringTag$1 = Symbol ? Symbol.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(value) { - if (value == null) { - return value === undefined ? undefinedTag : nullTag; - } - return (symToStringTag$1 && symToStringTag$1 in Object(value)) - ? getRawTag(value) - : objectToString(value); -} - -/** - * 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 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ -function isObjectLike(value) { - return value != null && typeof value == 'object'; -} - -/** `Object#toString` result references. */ -var symbolTag = '[object Symbol]'; - -/** - * Checks if `value` is classified as a `Symbol` primitive or object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. - * @example - * - * _.isSymbol(Symbol.iterator); - * // => true - * - * _.isSymbol('abc'); - * // => false - */ -function isSymbol(value) { - return typeof value == 'symbol' || - (isObjectLike(value) && baseGetTag(value) == symbolTag); -} - -/** Used as references for various `Number` constants. */ -var INFINITY = 1 / 0; - -/** Used to convert symbols to primitives and strings. */ -var symbolProto = Symbol ? Symbol.prototype : undefined, - symbolToString = symbolProto ? symbolProto.toString : undefined; - -/** - * The base implementation of `_.toString` which doesn't convert nullish - * values to empty strings. - * - * @private - * @param {*} value The value to process. - * @returns {string} Returns the string. - */ -function baseToString(value) { - // Exit early for strings to avoid a performance hit in some environments. - if (typeof value == 'string') { - return value; - } - if (isArray(value)) { - // Recursively convert values (susceptible to call stack limits). - return arrayMap(value, baseToString) + ''; - } - if (isSymbol(value)) { - return symbolToString ? symbolToString.call(value) : ''; - } - var result = (value + ''); - return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; -} - -/** - * The base implementation of `_.slice` without an iteratee call guard. - * - * @private - * @param {Array} array The array to slice. - * @param {number} [start=0] The start position. - * @param {number} [end=array.length] The end position. - * @returns {Array} Returns the slice of `array`. - */ -function baseSlice(array, start, end) { - var index = -1, - length = array.length; - - if (start < 0) { - start = -start > length ? 0 : (length + start); - } - end = end > length ? length : end; - if (end < 0) { - end += length; - } - length = start > end ? 0 : ((end - start) >>> 0); - start >>>= 0; - - var result = Array(length); - while (++index < length) { - result[index] = array[index + start]; - } - return result; -} - -/** - * Casts `array` to a slice if it's needed. - * - * @private - * @param {Array} array The array to inspect. - * @param {number} start The start position. - * @param {number} [end=array.length] The end position. - * @returns {Array} Returns the cast slice. - */ -function castSlice(array, start, end) { - var length = array.length; - end = end === undefined ? length : end; - return (!start && end >= length) ? array : baseSlice(array, start, end); -} - -/** - * The base implementation of `_.findIndex` and `_.findLastIndex` without - * support for iteratee shorthands. - * - * @private - * @param {Array} array The array to inspect. - * @param {Function} predicate The function invoked per iteration. - * @param {number} fromIndex The index to search from. - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {number} Returns the index of the matched value, else `-1`. - */ -function baseFindIndex(array, predicate, fromIndex, fromRight) { - var length = array.length, - index = fromIndex + (fromRight ? 1 : -1); - - while ((fromRight ? index-- : ++index < length)) { - if (predicate(array[index], index, array)) { - return index; - } - } - return -1; -} - -/** - * The base implementation of `_.isNaN` without support for number objects. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. - */ -function baseIsNaN(value) { - return value !== value; -} - -/** - * A specialized version of `_.indexOf` which performs strict equality - * comparisons of values, i.e. `===`. - * - * @private - * @param {Array} array The array to inspect. - * @param {*} value The value to search for. - * @param {number} fromIndex The index to search from. - * @returns {number} Returns the index of the matched value, else `-1`. - */ -function strictIndexOf(array, value, fromIndex) { - var index = fromIndex - 1, - length = array.length; - - while (++index < length) { - if (array[index] === value) { - return index; - } - } - return -1; -} - -/** - * The base implementation of `_.indexOf` without `fromIndex` bounds checks. - * - * @private - * @param {Array} array The array to inspect. - * @param {*} value The value to search for. - * @param {number} fromIndex The index to search from. - * @returns {number} Returns the index of the matched value, else `-1`. - */ -function baseIndexOf(array, value, fromIndex) { - return value === value - ? strictIndexOf(array, value, fromIndex) - : baseFindIndex(array, baseIsNaN, fromIndex); -} - -/** - * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol - * that is not found in the character symbols. - * - * @private - * @param {Array} strSymbols The string symbols to inspect. - * @param {Array} chrSymbols The character symbols to find. - * @returns {number} Returns the index of the last unmatched string symbol. - */ -function charsEndIndex(strSymbols, chrSymbols) { - var index = strSymbols.length; - - while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} - return index; -} - -/** - * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol - * that is not found in the character symbols. - * - * @private - * @param {Array} strSymbols The string symbols to inspect. - * @param {Array} chrSymbols The character symbols to find. - * @returns {number} Returns the index of the first unmatched string symbol. - */ -function charsStartIndex(strSymbols, chrSymbols) { - var index = -1, - length = strSymbols.length; - - while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} - return index; -} - -/** - * Converts an ASCII `string` to an array. - * - * @private - * @param {string} string The string to convert. - * @returns {Array} Returns the converted array. - */ -function asciiToArray(string) { - return string.split(''); -} - -/** Used to compose unicode character classes. */ -var rsAstralRange = '\\ud800-\\udfff', - rsComboMarksRange = '\\u0300-\\u036f', - reComboHalfMarksRange = '\\ufe20-\\ufe2f', - rsComboSymbolsRange = '\\u20d0-\\u20ff', - rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, - rsVarRange = '\\ufe0e\\ufe0f'; - -/** Used to compose unicode capture groups. */ -var rsZWJ = '\\u200d'; - -/** 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/). */ -var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); - -/** - * Checks if `string` contains Unicode symbols. - * - * @private - * @param {string} string The string to inspect. - * @returns {boolean} Returns `true` if a symbol is found, else `false`. - */ -function hasUnicode(string) { - return reHasUnicode.test(string); -} - -/** Used to compose unicode character classes. */ -var rsAstralRange$1 = '\\ud800-\\udfff', - rsComboMarksRange$1 = '\\u0300-\\u036f', - reComboHalfMarksRange$1 = '\\ufe20-\\ufe2f', - rsComboSymbolsRange$1 = '\\u20d0-\\u20ff', - rsComboRange$1 = rsComboMarksRange$1 + reComboHalfMarksRange$1 + rsComboSymbolsRange$1, - rsVarRange$1 = '\\ufe0e\\ufe0f'; - -/** Used to compose unicode capture groups. */ -var rsAstral = '[' + rsAstralRange$1 + ']', - rsCombo = '[' + rsComboRange$1 + ']', - rsFitz = '\\ud83c[\\udffb-\\udfff]', - rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', - rsNonAstral = '[^' + rsAstralRange$1 + ']', - rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', - rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', - rsZWJ$1 = '\\u200d'; - -/** Used to compose unicode regexes. */ -var reOptMod = rsModifier + '?', - rsOptVar = '[' + rsVarRange$1 + ']?', - rsOptJoin = '(?:' + rsZWJ$1 + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', - rsSeq = rsOptVar + reOptMod + rsOptJoin, - rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; - -/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ -var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); - -/** - * Converts a Unicode `string` to an array. - * - * @private - * @param {string} string The string to convert. - * @returns {Array} Returns the converted array. - */ -function unicodeToArray(string) { - return string.match(reUnicode) || []; -} - -/** - * Converts `string` to an array. - * - * @private - * @param {string} string The string to convert. - * @returns {Array} Returns the converted array. - */ -function stringToArray(string) { - return hasUnicode(string) - ? unicodeToArray(string) - : asciiToArray(string); -} - -/** - * Converts `value` to a string. An empty string is returned for `null` - * and `undefined` values. The sign of `-0` is preserved. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - * @example - * - * _.toString(null); - * // => '' - * - * _.toString(-0); - * // => '-0' - * - * _.toString([1, 2, 3]); - * // => '1,2,3' - */ -function toString(value) { - return value == null ? '' : baseToString(value); -} - -/** Used to match leading and trailing whitespace. */ -var reTrim = /^\s+|\s+$/g; - -/** - * Removes leading and trailing whitespace or specified characters from `string`. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category String - * @param {string} [string=''] The string to trim. - * @param {string} [chars=whitespace] The characters to trim. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {string} Returns the trimmed string. - * @example - * - * _.trim(' abc '); - * // => 'abc' - * - * _.trim('-_-abc-_-', '_-'); - * // => 'abc' - * - * _.map([' foo ', ' bar '], _.trim); - * // => ['foo', 'bar'] - */ -function trim(string, chars, guard) { - string = toString(string); - if (string && (guard || chars === undefined)) { - return string.replace(reTrim, ''); - } - if (!string || !(chars = baseToString(chars))) { - return string; - } - var strSymbols = stringToArray(string), - chrSymbols = stringToArray(chars), - start = charsStartIndex(strSymbols, chrSymbols), - end = charsEndIndex(strSymbols, chrSymbols) + 1; - - return castSlice(strSymbols, start, end).join(''); -} - -/** - * Check several parameter that there is something in the param - * @param {*} param input - * @return {boolean} - */ - var isNotEmpty = function (a) { - if (isArray(a)) { - return true; - } - return a !== undefined && a !== null && trim(a) !== ''; -}; - -/** `Object#toString` result references. */ -var numberTag = '[object Number]'; - -/** - * 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 - * - * _.isNumber('3'); - * // => false - */ -function isNumber(value) { - return typeof value == 'number' || - (isObjectLike(value) && baseGetTag(value) == numberTag); -} - -/** - * 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 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. - * @example - * - * _.isNaN(NaN); - * // => true - * - * _.isNaN(new Number(NaN)); - * // => true - * - * isNaN(undefined); - * // => true - * - * _.isNaN(undefined); - * // => false - */ -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; -} - -/** `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 - * - * _.isString(1); - * // => false - */ -function isString(value) { - return typeof value == 'string' || - (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); -} - -// 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) ) -}; - -// validate string type -/** - * @param {string} value expected value - * @return {boolean} true if OK - */ -var checkIsString = function(value) { - return (trim(value) !== '') ? isString(value) : false; -}; - -// check for boolean - -/** - * @param {boolean} value expected - * @return {boolean} true if OK - */ -var checkIsBoolean = function(value) { - return value !== null && value !== undefined && typeof value === 'boolean' -}; - -// validate any thing only check if there is something - -/** - * @param {*} value the value - * @param {boolean} [checkNull=true] strict check if there is null value - * @return {boolean} true is OK - */ -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; -}; - -// 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!'; -// @TODO the jsdoc return array. and we should also allow array syntax -var DEFAULT_TYPE$1 = DEFAULT_TYPE; -var ARRAY_TYPE_LFT$1 = ARRAY_TYPE_LFT; -var ARRAY_TYPE_RGT$1 = ARRAY_TYPE_RGT; - -var TYPE_KEY$1 = TYPE_KEY; -var OPTIONAL_KEY$1 = OPTIONAL_KEY; -var ENUM_KEY$1 = ENUM_KEY; -var ARGS_KEY$1 = ARGS_KEY; -var CHECKER_KEY$1 = CHECKER_KEY; -var ALIAS_KEY$1 = ALIAS_KEY; - -var ARRAY_TYPE$1 = ARRAY_TYPE; -var OBJECT_TYPE$1 = OBJECT_TYPE; -var STRING_TYPE$1 = STRING_TYPE; -var BOOLEAN_TYPE$1 = BOOLEAN_TYPE; -var NUMBER_TYPE$1 = NUMBER_TYPE; -var KEY_WORD$1 = KEY_WORD; -var OR_SEPERATOR$1 = OR_SEPERATOR; - -// not actually in use -// export const NUMBER_TYPES = JSONQL_CONSTANTS.NUMBER_TYPES; - -// primitive types - -/** - * 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 - */ -var combineFn = function(type) { - switch (type) { - case NUMBER_TYPE$1: - return checkIsNumber; - case STRING_TYPE$1: - return checkIsString; - case BOOLEAN_TYPE$1: - return checkIsBoolean; - default: - return checkIsAny; - } -}; - -// validate array type - -/** - * @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 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 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) > -1 && type.indexOf(ARRAY_TYPE_RGT$1) > -1) { - var _type = type.replace(ARRAY_TYPE_LFT$1, '').replace(ARRAY_TYPE_RGT$1, ''); - if (_type.indexOf(OR_SEPERATOR$1)) { - return _type.split(OR_SEPERATOR$1) - } - return [_type] - } - return false; -}; - -/** - * 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 - */ -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; -}; - -/** - * 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); - -/** `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 `_.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 = []; - - while (++index < length) { - var value = array[index]; - if (predicate(value, index, array)) { - result[resIndex++] = value; - } - } - return result; -} - -/** - * 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(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 = createBaseFor(); - -/** - * 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(n, iteratee) { - var index = -1, - result = Array(n); - - while (++index < n) { - result[index] = iteratee(index); - } - return result; -} - -/** `Object#toString` result references. */ -var argsTag = '[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(value) { - return isObjectLike(value) && baseGetTag(value) == argsTag; -} - -/** Used for built-in method references. */ -var objectProto$3 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$2 = objectProto$3.hasOwnProperty; - -/** Built-in value references. */ -var propertyIsEnumerable = objectProto$3.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$2.call(value, 'callee') && - !propertyIsEnumerable.call(value, 'callee'); -}; - -/** - * 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; -} - -/** Detect free variable `exports`. */ -var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; - -/** 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; - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeIsBuffer = Buffer ? Buffer.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 = nativeIsBuffer || stubFalse; - -/** Used as references for various `Number` constants. */ -var MAX_SAFE_INTEGER = 9007199254740991; - -/** Used to detect unsigned integer values. */ -var reIsUint = /^(?: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(value, length) { - var type = typeof value; - length = length == null ? MAX_SAFE_INTEGER : length; - - return !!length && - (type == 'number' || - (type != 'symbol' && reIsUint.test(value))) && - (value > -1 && value % 1 == 0 && value < length); -} - -/** Used as references for various `Number` constants. */ -var MAX_SAFE_INTEGER$1 = 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(value) { - return typeof value == 'number' && - value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER$1; -} - -/** `Object#toString` result references. */ -var argsTag$1 = '[object Arguments]', - arrayTag = '[object Array]', - boolTag = '[object Boolean]', - dateTag = '[object Date]', - errorTag = '[object Error]', - funcTag = '[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] = -typedArrayTags[mapTag] = typedArrayTags[numberTag$1] = -typedArrayTags[objectTag$1] = typedArrayTags[regexpTag] = -typedArrayTags[setTag] = typedArrayTags[stringTag$1] = -typedArrayTags[weakMapTag] = 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(value) { - return isObjectLike(value) && - isLength(value.length) && !!typedArrayTags[baseGetTag(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(func) { - return function(value) { - return func(value); - }; -} - -/** 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; - -/** Detect free variable `process` from Node.js. */ -var freeProcess = moduleExports$1 && freeGlobal.process; - -/** Used to access faster Node.js helpers. */ -var nodeUtil = (function() { - try { - // Use `util.types` for Node.js 10+. - var types = freeModule$1 && freeModule$1.require && freeModule$1.require('util').types; - - 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; - -/** - * 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 = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; - -/** Used for built-in method references. */ -var objectProto$4 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$3 = objectProto$4.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(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$3.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; -} - -/** Used for built-in method references. */ -var objectProto$5 = 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$5; - - return value === proto; -} - -/* 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$6 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$4 = objectProto$6.hasOwnProperty; - -/** - * 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 baseKeys(object) { - if (!isPrototype(object)) { - return nativeKeys(object); - } - var result = []; - for (var key in Object(object)) { - if (hasOwnProperty$4.call(object, key) && key != 'constructor') { - result.push(key); - } - } - return result; -} - -/** - * 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(value) { - var type = typeof value; - return value != null && (type == 'object' || type == 'function'); -} - -/** `Object#toString` result references. */ -var asyncTag = '[object AsyncFunction]', - funcTag$1 = '[object Function]', - genTag = '[object GeneratorFunction]', - proxyTag = '[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(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$1 || tag == genTag || tag == asyncTag || tag == proxyTag; -} - -/** - * 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$1(value) { - return value != null && isLength(value.length) && !isFunction(value); -} - -/** - * 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); -} - -/** - * 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); -} - -/** - * Removes all key-value entries from the list cache. - * - * @private - * @name clear - * @memberOf ListCache - */ -function listCacheClear() { - this.__data__ = []; - this.size = 0; -} - -/** - * 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(value, other) { - return value === other || (value !== value && other !== other); -} - -/** - * 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(array, key) { - var length = array.length; - while (length--) { - if (eq(array[length][0], key)) { - return length; - } - } - return -1; -} - -/** 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. - * - * @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(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; -} - -/** - * 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. - */ -function listCacheGet(key) { - var data = this.__data__, - index = assocIndexOf(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(key) { - return assocIndexOf(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(key, value) { - var data = this.__data__, - index = assocIndexOf(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(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.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. - * - * @private - * @name clear - * @memberOf Stack - */ -function stackClear() { - this.__data__ = new ListCache; - 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(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(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(key) { - return this.__data__.has(key); -} - -/** Used to detect overreaching core-js shims. */ -var coreJsData = root['__core-js_shared__']; - -/** 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) : ''; -}()); - -/** - * 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(func) { - return !!maskSrcKey && (maskSrcKey in func); -} - -/** Used for built-in method references. */ -var funcProto$1 = Function.prototype; - -/** Used to resolve the decompiled source of functions. */ -var funcToString$1 = funcProto$1.toString; - -/** - * 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 ''; -} - -/** - * 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$7 = 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$5 = objectProto$7.hasOwnProperty; - -/** Used to detect if a method is native. */ -var reIsNative = RegExp('^' + - funcToString$2.call(hasOwnProperty$5).replace(reRegExpChar, '\\$&') - .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(value) { - if (!isObject(value) || isMasked(value)) { - return false; - } - var pattern = isFunction(value) ? reIsNative : reIsHostCtor; - return pattern.test(toSource(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(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(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'); - -/* Built-in method references that are verified to be native. */ -var nativeCreate = getNative(Object, 'create'); - -/** - * Removes all key-value entries from the hash. - * - * @private - * @name clear - * @memberOf Hash - */ -function hashClear() { - this.__data__ = nativeCreate ? nativeCreate(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(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 = '__lodash_hash_undefined__'; - -/** Used for built-in method references. */ -var objectProto$8 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$6 = objectProto$8.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(key) { - var data = this.__data__; - if (nativeCreate) { - var result = data[key]; - return result === HASH_UNDEFINED ? undefined : result; - } - return hasOwnProperty$6.call(data, key) ? data[key] : undefined; -} - -/** Used for built-in method references. */ -var objectProto$9 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$7 = objectProto$9.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(key) { - var data = this.__data__; - return nativeCreate ? (data[key] !== undefined) : hasOwnProperty$7.call(data, key); -} - -/** Used to stand-in for `undefined` hash values. */ -var HASH_UNDEFINED$1 = '__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(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. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ -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]); - } -} - -// 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. - * - * @private - * @name clear - * @memberOf MapCache - */ -function mapCacheClear() { - this.size = 0; - this.__data__ = { - 'hash': new Hash, - 'map': new (Map$1 || ListCache), - 'string': new Hash - }; -} - -/** - * 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(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(map, key) { - var data = map.__data__; - return isKeyable(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(key) { - var result = getMapData(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(key) { - return getMapData(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(key) { - return getMapData(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(key, value) { - var data = getMapData(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(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.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 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. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ -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; - -/** Used to stand-in for `undefined` hash values. */ -var HASH_UNDEFINED$2 = '__lodash_hash_undefined__'; - -/** - * 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; -} - -/** - * 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); -} - -/** - * - * Creates an array cache object to store unique values. - * - * @private - * @constructor - * @param {Array} [values] The values to cache. - */ -function SetCache(values) { - var index = -1, - length = values == null ? 0 : values.length; - - this.__data__ = new MapCache; - while (++index < length) { - this.add(values[index]); - } -} - -// Add methods to `SetCache`. -SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; -SetCache.prototype.has = setCacheHas; - -/** - * 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; - - while (++index < length) { - if (predicate(array[index], index, array)) { - return true; - } - } - return false; -} - -/** - * 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`. - */ -function cacheHas(cache, key) { - return cache.has(key); -} - -/** Used to compose bitmasks for value comparisons. */ -var COMPARE_PARTIAL_FLAG = 1, - COMPARE_UNORDERED_FLAG = 2; - -/** - * 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; - - 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; - - stack.set(array, other); - stack.set(other, array); - - // Ignore non-index properties. - while (++index < arrLength) { - var arrValue = array[index], - othValue = other[index]; - - 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; -} - -/** Built-in value references. */ -var Uint8Array = root.Uint8Array; - -/** - * 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); - - map.forEach(function(value, key) { - result[++index] = [key, value]; - }); - return result; -} - -/** - * 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); - - set.forEach(function(value) { - result[++index] = value; - }); - return result; -} - -/** Used to compose bitmasks for value comparisons. */ -var COMPARE_PARTIAL_FLAG$1 = 1, - COMPARE_UNORDERED_FLAG$1 = 2; - -/** `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]'; - -var arrayBufferTag$1 = '[object ArrayBuffer]', - dataViewTag$1 = '[object DataView]'; - -/** Used to convert symbols to primitives and strings. */ -var symbolProto$1 = Symbol ? Symbol.prototype : undefined, - symbolValueOf = symbolProto$1 ? symbolProto$1.valueOf : undefined; - -/** - * 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; - - case arrayBufferTag$1: - if ((object.byteLength != other.byteLength) || - !equalFunc(new Uint8Array(object), new Uint8Array(other))) { - return false; - } - return true; - - 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); - - case errorTag$1: - return object.name == other.name && object.message == other.message; - - 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 + ''); - - case mapTag$1: - var convert = mapToArray; - - case setTag$1: - var isPartial = bitmask & COMPARE_PARTIAL_FLAG$1; - convert || (convert = setToArray); - - 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; - - // 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; - - case symbolTag$1: - if (symbolValueOf) { - return symbolValueOf.call(object) == symbolValueOf.call(other); - } - } - 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; - - while (++index < length) { - array[offset + index] = values[index]; - } - return array; -} - -/** - * 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)); -} - -/** - * 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 []; -} - -/** Used for built-in method references. */ -var objectProto$a = Object.prototype; - -/** Built-in value references. */ -var propertyIsEnumerable$1 = objectProto$a.propertyIsEnumerable; - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeGetSymbols = Object.getOwnPropertySymbols; - -/** - * 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); - }); -}; - -/** - * 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); -} - -/** Used to compose bitmasks for value comparisons. */ -var COMPARE_PARTIAL_FLAG$2 = 1; - -/** Used for built-in method references. */ -var objectProto$b = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$8 = objectProto$b.hasOwnProperty; - -/** - * 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; - - if (objLength != othLength && !isPartial) { - return false; - } - var index = objLength; - while (index--) { - var key = objProps[index]; - if (!(isPartial ? key in other : hasOwnProperty$8.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); - - var skipCtor = isPartial; - while (++index < objLength) { - key = objProps[index]; - var objValue = object[key], - othValue = other[key]; - - 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; - - // 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; -} - -/* Built-in method references that are verified to be native. */ -var DataView = getNative(root, 'DataView'); - -/* Built-in method references that are verified to be native. */ -var Promise$1 = getNative(root, 'Promise'); - -/* Built-in method references that are verified to be native. */ -var Set$1 = getNative(root, 'Set'); - -/* Built-in method references that are verified to be native. */ -var WeakMap$1 = getNative(root, 'WeakMap'); - -/** `Object#toString` result references. */ -var mapTag$2 = '[object Map]', - objectTag$2 = '[object Object]', - promiseTag = '[object Promise]', - setTag$2 = '[object Set]', - weakMapTag$1 = '[object WeakMap]'; - -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); - -/** - * Gets the `toStringTag` of `value`. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ -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; - }; -} - -var getTag$1 = getTag; - -/** Used to compose bitmasks for value comparisons. */ -var COMPARE_PARTIAL_FLAG$3 = 1; - -/** `Object#toString` result references. */ -var argsTag$2 = '[object Arguments]', - arrayTag$1 = '[object Array]', - objectTag$3 = '[object Object]'; - -/** Used for built-in method references. */ -var objectProto$c = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$9 = objectProto$c.hasOwnProperty; - -/** - * 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`. - */ -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); - - 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; - } - 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$9.call(object, '__wrapped__'), - othIsWrapped = othIsObj && hasOwnProperty$9.call(other, '__wrapped__'); - - if (objIsWrapped || othIsWrapped) { - var objUnwrapped = objIsWrapped ? object.value() : object, - othUnwrapped = othIsWrapped ? other.value() : other; - - 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); -} - -/** - * 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); -} - -/** Used to compose bitmasks for value comparisons. */ -var COMPARE_PARTIAL_FLAG$4 = 1, - COMPARE_UNORDERED_FLAG$2 = 2; - -/** - * 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; - - 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]; - - 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; -} - -/** - * 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); -} - -/** - * 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; - - while (length--) { - var key = result[length], - value = object[key]; - - result[length] = [key, value, isStrictComparable(value)]; - } - return result; -} - -/** - * 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. - */ -function matchesStrictComparable(key, srcValue) { - return function(object) { - if (object == null) { - return false; - } - return object[key] === srcValue && - (srcValue !== undefined || (key in Object(object))); - }; -} - -/** - * 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. - */ -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); - }; -} - -/** Used to match property names within property paths. */ -var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, - reIsPlainProp = /^\w*$/; - -/** - * 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`. - */ -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'; - -/** - * 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; - */ -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; -} - -// Expose `MapCache`. -memoize.Cache = MapCache; - -/** Used as the maximum memoize cache size. */ -var MAX_MEMOIZE_SIZE = 500; - -/** - * 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(); - } - return key; - }); - - var cache = result.cache; - return result; -} - -/** Used to match property names within property paths. */ -var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; - -/** Used to match backslashes in property paths. */ -var reEscapeChar = /\\(\\)?/g; - -/** - * 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; -}); - -/** - * 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)); -} - -/** Used as references for various `Number` constants. */ -var INFINITY$1 = 1 / 0; - -/** - * 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; -} - -/** - * 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); - }; -} - -/** - * 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(value) { - return value; -} - -/** - * 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); -} - -// 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; - - 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; -}; - -/** - * fold this into it's own function to handler different object type - * @param {object} p the prepared object for process - * @return {boolean} - */ -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) -}; - -// 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 - -/** - * 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 - */ -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; -}; - -/** - * actually picking the validator - * @param {*} type for checking - * @param {*} value for checking - * @return {boolean} true on OK - */ -var validateHandler = function(type, value) { - var tmp; - switch (true) { - case type === OBJECT_TYPE$1: - // debugFn('call OBJECT_TYPE') - return !objectTypeHandler(value) - case type === ARRAY_TYPE$1: - // 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) - } -}; - -/** - * 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 - */ -var getOptionalValue = function(arg, param) { - if (arg !== undefined) { - return arg; - } - return (param.optional === true && param.defaultvalue !== undefined ? param.defaultvalue : null) -}; - -/** - * 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 - */ -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 JsonqlError(PARAMS_NOT_ARRAY_ERR) - } - if (params.length === 0) { - return []; - } - if (!checkIsArray(args)) { - throw new JsonqlError(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$1 ]; - // 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(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([]) - }) -}; - -var defineProperty = (function() { - try { - var func = getNative(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(object, key, value) { - if (key == '__proto__' && defineProperty) { - defineProperty(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(object, key, value) { - if ((value !== undefined && !eq(object[key], value)) || - (value === undefined && !(key in object))) { - baseAssignValue(object, key, 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; - -/** Built-in value references. */ -var Buffer$1 = moduleExports$2 ? root.Buffer : undefined, - allocUnsafe = Buffer$1 ? Buffer$1.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(buffer, isDeep) { - if (isDeep) { - return buffer.slice(); - } - var length = buffer.length, - result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); - - buffer.copy(result); - return result; -} - -/** - * Creates a clone of `arrayBuffer`. - * - * @private - * @param {ArrayBuffer} arrayBuffer The array buffer to clone. - * @returns {ArrayBuffer} Returns the cloned array buffer. - */ -function cloneArrayBuffer(arrayBuffer) { - var result = new arrayBuffer.constructor(arrayBuffer.byteLength); - new Uint8Array(result).set(new Uint8Array(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(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]; - } - return array; -} - -/** 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; - }; -}()); - -/** - * Initializes an object clone. - * - * @private - * @param {Object} object The object to clone. - * @returns {Object} Returns the initialized clone. - */ -function initCloneObject(object) { - return (typeof object.constructor == 'function' && !isPrototype(object)) - ? baseCreate(getPrototype(object)) - : {}; -} - -/** - * 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(value) { - return isObjectLike(value) && isArrayLike$1(value); -} - -/** - * 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(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$d = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$a = objectProto$d.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(object, key, value) { - var objValue = object[key]; - if (!(hasOwnProperty$a.call(object, key) && eq(objValue, value)) || - (value === undefined && !(key in object))) { - baseAssignValue(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(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(object, key, newValue); - } else { - assignValue(object, key, newValue); - } - } - return object; -} - -/** - * 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(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$e = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$b = objectProto$e.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(object) { - if (!isObject(object)) { - return nativeKeysIn(object); - } - var isProto = isPrototype(object), - result = []; - - for (var key in object) { - if (!(key == 'constructor' && (isProto || !hasOwnProperty$b.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(object) { - return isArrayLike$1(object) ? arrayLikeKeys(object, true) : baseKeysIn(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(value) { - return copyObject(value, keysIn(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(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); -} - -/** - * 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; - - if (newValue === undefined) { - newValue = srcValue; - } - assignMergeValue(object, key, newValue); - } - }, keysIn); -} - -/** - * 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]); - } - return func.apply(thisArg, args); -} - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeMax = 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(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); - - 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); - }; -} - -/** - * 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; - }; -} - -/** - * 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; - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeNow = Date.now; - -/** - * 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. - */ -function shortOut(func) { - var count = 0, - lastCalled = 0; - - return function() { - var stamp = nativeNow(), - remaining = HOT_SPAN - (stamp - lastCalled); - - lastCalled = stamp; - if (remaining > 0) { - if (++count >= HOT_COUNT) { - return arguments[0]; - } - } else { - count = 0; - } - return func.apply(undefined, arguments); - }; -} - -/** - * 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); - -/** - * 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 + ''); -} - -/** - * 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; -} - -/** - * Creates a function like `_.assign`. - * - * @private - * @param {Function} assigner The function to assign values. - * @returns {Function} Returns the new assigner function. - */ -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; - - customizer = (assigner.length > 3 && typeof customizer == 'function') - ? (length--, customizer) - : undefined; - - 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; - }); -} - -/** - * 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); -}); - -/** - * 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 = 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$1]; } ); - 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(_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 - } -} - -/** - * 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$1] === true && isEmpty(config[key])) - ? merge({}, value, ( obj = {}, obj[KEY_WORD$1] = true, obj )) - : ( obj$1 = {}, obj$1[ARGS_KEY$1] = config[key], obj$1[TYPE_KEY$1] = value[TYPE_KEY$1], obj$1[OPTIONAL_KEY$1] = value[OPTIONAL_KEY$1] || false, obj$1[ENUM_KEY$1] = value[ENUM_KEY$1] || false, obj$1[CHECKER_KEY$1] = value[CHECKER_KEY$1] || 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 = 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 = 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$1] ], - [( obj = {}, obj[TYPE_KEY$1] = toArray(value[TYPE_KEY$1]), obj[OPTIONAL_KEY$1] = value[OPTIONAL_KEY$1], 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; -}; - -/** - * 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$1]) { - return value[ARGS_KEY$1] - } - var check = validateHandler$1(value, cb); - if (check.length) { - // log('runValidationAction', key, value) - throw new JsonqlTypeError(key, check) - } - if (value[ENUM_KEY$1] !== false && !enumHandler(value[ARGS_KEY$1], value[ENUM_KEY$1])) { - // log(ENUM_KEY, value[ENUM_KEY]) - throw new JsonqlEnumError(key) - } - if (value[CHECKER_KEY$1] !== false && !checkerHandler(value[ARGS_KEY$1], value[CHECKER_KEY$1])) { - // log(CHECKER_KEY, value[CHECKER_KEY]) - throw new JsonqlCheckerError(key) - } - return value[ARGS_KEY$1] - } -} - -/** - * @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 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) { - /** - * 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= {}; - - 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); - -// bunch of generic helpers - -/** - * 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; }; - -// quick and dirty to turn non array to array -var toArray$1 = function (arg) { return isArray(arg) ? arg : [arg]; }; - -/** - * @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; - /* - console.info('obj', obj) - console.error(e) - throw new Error(e) - */ - } -}; - -/** - * 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('_'); -}; - -/** - * 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))); -}; - -/** - * 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$1(value)) - ); }, Reflect.apply(mainFn, null, args)) - ); - } -); -}; - -// break it out on its own because - - -/** - * This one return a different result from the chainPromises - * it will be the same like chainFns that take one promise resolve as the next fn parameter - * @param {function} initPromise a function that accept param and resolve result - * @param {array} promises array of function pass that resolve promises - * @return {promise} resolve the processed result - */ -function chainProcessPromises(initPromise) { - var promises = [], len = arguments.length - 1; - while ( len-- > 0 ) promises[ len ] = arguments[ len + 1 ]; - - return function () { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - return ( - promises.reduce(function (promiseChain, currentTask) { return ( - promiseChain.then(function (chainResult) { return ( - currentTask(chainResult) - ); } - ) - ); }, Reflect.apply(initPromise, null, args)) - ); - } -} - -/** - * 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; - - if (Object.getOwnPropertyDescriptor(obj, name) === undefined) { - Object.defineProperty(obj, name, { - set: setter, - get: getter === null ? function() { return null; } : getter - }); - } - return obj -} - -/** - * 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; -} - -/** - * 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; - - var check = objHasProp(resolver, name); - if (overwrite === false && check !== undefined) { - // console.info(`NOT INJECTED`) - return resolver; - } - /* this will throw error! - 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 - }); - - return resolver; -} - -// 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) - ) -} - -/** - * 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; -} - -/** - * 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')) { - return contract.socket; - } - return false; -} - -/** - * @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 - * @param {boolean} [fallback=false] this is a fall back option for old code - * @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, fallback) { - if ( fallback === void 0 ) fallback = false; - - var socket = extractSocketPart(contract); - if (socket === false) { - if (fallback) { - return contract; // just return the whole contract - } - throw new JsonqlError("socket not found in contract!") - } - var nspSet = {}; - var size = 0; - var publicNamespace; - for (var resolverName in socket) { - var params = socket[resolverName]; - var namespace = params.namespace; - if (namespace) { - if (!nspSet[namespace]) { - ++size; - nspSet[namespace] = {}; - } - nspSet[namespace][resolverName] = params; - if (!publicNamespace) { - if (params.public) { - publicNamespace = namespace; - } - } - } - } - return { size: size, nspSet: nspSet, publicNamespace: publicNamespace } -} - -/** - * @NOTE ported from jsonql-ws-client - * Got to make sure the connection order otherwise - * it will hang - * @param {object} nspSet contract - * @param {string} publicNamespace like the name said - * @return {array} namespaces in order - */ -function getNamespaceInOrder(nspSet, publicNamespace) { - var names = []; // need to make sure the order! - for (var namespace in nspSet) { - if (namespace === publicNamespace) { - names[1] = namespace; - } else { - names[0] = namespace; - } - } - return names; -} - -/** - * @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 ) -); -}; - -/** - * Get name from the payload (ported back from jsonql-koa) - * @param {*} payload to extract from - * @return {string} name - */ -function getNameFromPayload(payload) { - return Object.keys(payload)[0] -} - -/** - * 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)) -} - -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) -} -// wrapper to make sure it string -function hashCode2Str(s) { - return hashCode(s) + '' -} - -// making all the functionality on it's own -// import { WatchClass } from './watch' - -var SuspendClass = function SuspendClass() { - // suspend, release and queue - this.__suspend__ = null; - this.queueStore = new Set(); - /* - this.watch('suspend', function(value, prop, oldValue) { - this.logger(`${prop} set from ${oldValue} to ${value}`) - // it means it set the suspend = true then release it - if (oldValue === true && value === false) { - // we want this happen after the return happens - setTimeout(() => { - this.release() - }, 1) - } - return value; // we need to return the value to store it - }) - */ -}; - -var prototypeAccessors = { $suspend: { configurable: true },$queues: { configurable: true } }; - -/** - * setter to set the suspend and check if it's boolean value - * @param {boolean} value to trigger - */ -prototypeAccessors.$suspend.set = function (value) { - var this$1 = this; - - if (typeof value === 'boolean') { - var lastValue = this.__suspend__; - this.__suspend__ = value; - this.logger('($suspend)', ("Change from " + lastValue + " --> " + value)); - if (lastValue === true && value === false) { - setTimeout(function () { - this$1.release(); - }, 1); - } - } else { - throw new Error("$suspend only accept Boolean value!") - } -}; - -/** - * queuing call up when it's in suspend mode - * @param {any} value - * @return {Boolean} true when added or false when it's not - */ -SuspendClass.prototype.$queue = function $queue () { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - if (this.__suspend__ === true) { - this.logger('($queue)', 'added to $queue', args); - // there shouldn't be any duplicate ... - this.queueStore.add(args); - } - return this.__suspend__; -}; - -/** - * 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 [] -}; - -/** - * Release the queue - * @return {int} size if any - */ -SuspendClass.prototype.release = function release () { - var this$1 = this; - - var size = this.queueStore.size; - this.logger('(release)', ("Release was called " + size)); - if (size > 0) { - var queue = Array.from(this.queueStore); - this.queueStore.clear(); - this.logger('queue', queue); - queue.forEach(function (args) { - this$1.logger(args); - Reflect.apply(this$1.$trigger, this$1, args); - }); - this.logger(("Release size " + (this.queueStore.size))); - } -}; - -Object.defineProperties( SuspendClass.prototype, prototypeAccessors ); - -// break up the main file because its getting way too long - -var NbEventServiceBase = /*@__PURE__*/(function (SuspendClass) { - function NbEventServiceBase(config) { - if ( config === void 0 ) 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 ( SuspendClass ) NbEventServiceBase.__proto__ = SuspendClass; - NbEventServiceBase.prototype = Object.create( SuspendClass && SuspendClass.prototype ); - NbEventServiceBase.prototype.constructor = NbEventServiceBase; - - var prototypeAccessors = { is: { configurable: true },normalStore: { configurable: true },lazyStore: { configurable: true } }; - - // for id if the instance is this class - prototypeAccessors.is.get = function () { - return 'nb-event-service' - }; - - /** - * validate the event name(s) - * @param {string[]} evt event name - * @return {boolean} true when OK - */ - NbEventServiceBase.prototype.validateEvt = function validateEvt () { - var this$1 = this; - var evt = [], len = arguments.length; - while ( len-- ) evt[ len ] = arguments[ len ]; - - evt.forEach(function (e) { - if (typeof e !== 'string') { - this$1.logger('(validateEvt)', e); - throw new Error("event name must be string type!") - } - }); - return true; - }; - - /** - * Simple quick check on the two main parameters - * @param {string} evt event name - * @param {function} callback function to call - * @return {boolean} true when OK - */ - NbEventServiceBase.prototype.validate = function validate (evt, callback) { - if (this.validateEvt(evt)) { - if (typeof callback === 'function') { - return true; - } - } - throw new Error("callback required to be function type!") - }; - - /** - * Check if this type is correct or not added in V1.5.0 - * @param {string} type for checking - * @return {boolean} true on OK - */ - NbEventServiceBase.prototype.validateType = function validateType (type) { - var types = ['on', 'only', 'once', 'onlyOnce']; - return !!types.filter(function (t) { return type === t; }).length; - }; - - /** - * Run the callback - * @param {function} callback function to execute - * @param {array} payload for callback - * @param {object} ctx context or null - * @return {void} the result store in $done - */ - NbEventServiceBase.prototype.run = function run (callback, payload, ctx) { - this.logger('(run)', callback, payload, ctx); - this.$done = Reflect.apply(callback, ctx, this.toArray(payload)); - }; - - /** - * Take the content out and remove it from store id by the name - * @param {string} evt event name - * @param {string} [storeName = lazyStore] name of store - * @return {object|boolean} content or false on not found - */ - NbEventServiceBase.prototype.takeFromStore = function takeFromStore (evt, storeName) { - if ( storeName === void 0 ) storeName = 'lazyStore'; - - var store = this[storeName]; // it could be empty at this point - if (store) { - this.logger('(takeFromStore)', storeName, store); - if (store.has(evt)) { - var content = store.get(evt); - this.logger('(takeFromStore)', ("has " + evt), content); - store.delete(evt); - return content; - } - return false; - } - throw new Error((storeName + " is not supported!")) - }; - - /** - * The add to store step is similar so make it generic for resuse - * @param {object} store which store to use - * @param {string} evt event name - * @param {spread} args because the lazy store and normal store store different things - * @return {array} store and the size of the store - */ - NbEventServiceBase.prototype.addToStore = function addToStore (store, evt) { - var args = [], len = arguments.length - 2; - while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; - - var fnSet; - if (store.has(evt)) { - this.logger('(addToStore)', (evt + " existed")); - fnSet = store.get(evt); - } else { - this.logger('(addToStore)', ("create new Set for " + evt)); - // this is new - fnSet = new Set(); - } - // lazy only store 2 items - this is not the case in V1.6.0 anymore - // we need to check the first parameter is string or not - if (args.length > 2) { - if (Array.isArray(args[0])) { // lazy store - // check if this type of this event already register in the lazy store - var t = args[2]; - if (!this.checkTypeInLazyStore(evt, t)) { - fnSet.add(args); - } - } 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] - }; - - /** - * @param {array} args for compare - * @param {object} fnSet A Set to search from - * @return {boolean} true on exist - */ - NbEventServiceBase.prototype.checkContentExist = function checkContentExist (args, fnSet) { - var list = Array.from(fnSet); - return !!list.filter(function (l) { - var hash = l[0]; - if (hash === args[0]) { - return true; - } - return false; - }).length; - }; - - /** - * get the existing type to make sure no mix type add to the same store - * @param {string} evtName event name - * @param {string} type the type to check - * @return {boolean} true you can add, false then you can't add this type - */ - NbEventServiceBase.prototype.checkTypeInStore = function checkTypeInStore (evtName, type) { - this.validateEvt(evtName, type); - var all = this.$get(evtName, true); - if (all === false) { - // pristine it means you can add - return true; - } - // it should only have ONE type in ONE event store - return !all.filter(function (list) { - var t = list[3]; - return type !== t; - }).length; - }; - - /** - * This is checking just the lazy store because the structure is different - * therefore we need to use a new method to check it - */ - NbEventServiceBase.prototype.checkTypeInLazyStore = function checkTypeInLazyStore (evtName, type) { - this.validateEvt(evtName, type); - var store = this.lazyStore.get(evtName); - this.logger('(checkTypeInLazyStore)', store); - if (store) { - return !!Array - .from(store) - .filter(function (l) { - var t = l[2]; - return t !== type; - }).length - } - return false; - }; - - /** - * wrapper to re-use the addToStore, - * V1.3.0 add extra check to see if this type can add to this evt - * @param {string} evt event name - * @param {string} type on or once - * @param {function} callback function - * @param {object} context the context the function execute in or null - * @return {number} size of the store - */ - NbEventServiceBase.prototype.addToNormalStore = function addToNormalStore (evt, type, callback, context) { - if ( context === void 0 ) context = null; - - this.logger('(addToNormalStore)', evt, type, 'try to add to normal store'); - // @TODO we need to check the existing store for the type first! - if (this.checkTypeInStore(evt, type)) { - this.logger('(addToNormalStore)', (type + " can add to " + evt + " normal store")); - var key = this.hashFnToKey(callback); - var args = [this.normalStore, evt, key, callback, context, type]; - var ref = Reflect.apply(this.addToStore, this, args); - var _store = ref[0]; - var size = ref[1]; - this.normalStore = _store; - return size; - } - return false; - }; - - /** - * Add to lazy store this get calls when the callback is not register yet - * so we only get a payload object or even nothing - * @param {string} evt event name - * @param {array} payload of arguments or empty if there is none - * @param {object} [context=null] the context the callback execute in - * @param {string} [type=false] register a type so no other type can add to this evt - * @return {number} size of the store - */ - NbEventServiceBase.prototype.addToLazyStore = function addToLazyStore (evt, payload, context, type) { - if ( payload === void 0 ) payload = []; - if ( context === void 0 ) context = null; - if ( type === void 0 ) type = false; - - // this is add in V1.6.0 - // when there is type then we will need to check if this already added in lazy store - // and no other type can add to this lazy store - var args = [this.lazyStore, evt, this.toArray(payload), context]; - if (type) { - args.push(type); - } - var ref = Reflect.apply(this.addToStore, this, args); - var _store = ref[0]; - var size = ref[1]; - this.lazyStore = _store; - return size; - }; - - /** - * make sure we store the argument correctly - * @param {*} arg could be array - * @return {array} make sured - */ - NbEventServiceBase.prototype.toArray = function toArray (arg) { - return Array.isArray(arg) ? arg : [arg]; - }; - - /** - * setter to store the Set in private - * @param {object} obj a Set - */ - prototypeAccessors.normalStore.set = function (obj) { - NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj); - }; - - /** - * @return {object} Set object - */ - prototypeAccessors.normalStore.get = function () { - return NB_EVENT_SERVICE_PRIVATE_STORE.get(this) - }; - - /** - * setter to store the Set in lazy store - * @param {object} obj a Set - */ - prototypeAccessors.lazyStore.set = function (obj) { - NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj); - }; - - /** - * @return {object} the lazy store Set - */ - prototypeAccessors.lazyStore.get = function () { - return NB_EVENT_SERVICE_PRIVATE_LAZY.get(this) - }; - - /** - * generate a hashKey to identify the function call - * The build-in store some how could store the same values! - * @param {function} fn the converted to string function - * @return {string} hashKey - */ - NbEventServiceBase.prototype.hashFnToKey = function hashFnToKey (fn) { - return hashCode2Str(fn.toString()) - }; - - Object.defineProperties( NbEventServiceBase.prototype, prototypeAccessors ); - - return NbEventServiceBase; -}(SuspendClass)); - -// The top level -// export -var EventService = /*@__PURE__*/(function (NbStoreService) { - function EventService(config) { - if ( config === void 0 ) config = {}; - - NbStoreService.call(this, config); - } - - if ( NbStoreService ) EventService.__proto__ = NbStoreService; - EventService.prototype = Object.create( NbStoreService && NbStoreService.prototype ); - EventService.prototype.constructor = EventService; - - var prototypeAccessors = { $done: { configurable: true } }; - - /** - * logger function for overwrite - */ - EventService.prototype.logger = function logger () {}; - - ////////////////////////// - // PUBLIC METHODS // - ////////////////////////// - - /** - * Register your evt handler, note we don't check the type here, - * we expect you to be sensible and know what you are doing. - * @param {string} evt name of event - * @param {function} callback bind method --> if it's array or not - * @param {object} [context=null] to execute this call in - * @return {number} the size of the store - */ - EventService.prototype.$on = function $on (evt , callback , context) { - var this$1 = this; - if ( context === void 0 ) context = null; - - var type = 'on'; - this.validate(evt, callback); - // first need to check if this evt is in lazy store - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register first then call later - if (lazyStoreContent === false) { - this.logger('($on)', (evt + " callback is not in lazy store")); - // @TODO we need to check if there was other listener to this - // event and are they the same type then we could solve that - // register the different type to the same event name - - return this.addToNormalStore(evt, type, callback, context) - } - this.logger('($on)', (evt + " found in lazy store")); - // this is when they call $trigger before register this callback - var size = 0; - lazyStoreContent.forEach(function (content) { - var payload = content[0]; - var ctx = content[1]; - var t = content[2]; - if (t && t !== type) { - throw new Error(("You are trying to register an event already been taken by other type: " + t)) - } - this$1.logger("($on)", ("call run on " + evt)); - this$1.run(callback, payload, context || ctx); - size += this$1.addToNormalStore(evt, type, callback, context || ctx); - }); - return size; - }; - - /** - * once only registered it once, there is no overwrite option here - * @NOTE change in v1.3.0 $once can add multiple listeners - * but once the event fired, it will remove this event (see $only) - * @param {string} evt name - * @param {function} callback to execute - * @param {object} [context=null] the handler execute in - * @return {boolean} result - */ - EventService.prototype.$once = function $once (evt , callback , context) { - if ( context === void 0 ) context = null; - - this.validate(evt, callback); - var type = 'once'; - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register before call $trigger - var nStore = this.normalStore; - if (lazyStoreContent === false) { - this.logger('($once)', (evt + " not in the lazy store")); - // v1.3.0 $once now allow to add multiple listeners - return this.addToNormalStore(evt, type, callback, context) - } else { - // now this is the tricky bit - // there is a potential bug here that cause by the developer - // if they call $trigger first, the lazy won't know it's a once call - // so if in the middle they register any call with the same evt name - // then this $once call will be fucked - add this to the documentation - this.logger('($once)', lazyStoreContent); - var list = Array.from(lazyStoreContent); - // should never have more than 1 - var ref = list[0]; - var payload = ref[0]; - var ctx = ref[1]; - var t = ref[2]; - if (t && t !== type) { - throw new Error(("You are trying to register an event already been taken by other type: " + t)) - } - this.logger('($once)', ("call run for " + evt)); - this.run(callback, payload, context || ctx); - // remove this evt from store - this.$off(evt); - } - }; - - /** - * This one event can only bind one callbackback - * @param {string} evt event name - * @param {function} callback event handler - * @param {object} [context=null] the context the event handler execute in - * @return {boolean} true bind for first time, false already existed - */ - EventService.prototype.$only = function $only (evt, callback, context) { - var this$1 = this; - if ( context === void 0 ) context = null; - - this.validate(evt, callback); - var type = 'only'; - var added = false; - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register before call $trigger - var nStore = this.normalStore; - if (!nStore.has(evt)) { - this.logger("($only)", (evt + " add to store")); - added = this.addToNormalStore(evt, type, callback, context); - } - if (lazyStoreContent !== false) { - // there are data store in lazy store - this.logger('($only)', (evt + " found data in lazy store to execute")); - var list = Array.from(lazyStoreContent); - // $only allow to trigger this multiple time on the single handler - list.forEach( function (l) { - var payload = l[0]; - var ctx = l[1]; - var t = l[2]; - if (t && t !== type) { - throw new Error(("You are trying to register an event already been taken by other type: " + t)) - } - this$1.logger("($only)", ("call run for " + evt)); - this$1.run(callback, payload, context || ctx); - }); - } - return added; - }; - - /** - * $only + $once this is because I found a very subtile bug when we pass a - * resolver, rejecter - and it never fire because that's OLD 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; - - this.validate(evt, callback); - var type = 'onlyOnce'; - var added = false; - var lazyStoreContent = this.takeFromStore(evt); - // this is normal register before call $trigger - var nStore = this.normalStore; - if (!nStore.has(evt)) { - this.logger("($onlyOnce)", (evt + " add to store")); - added = this.addToNormalStore(evt, type, callback, context); - } - if (lazyStoreContent !== false) { - // there are data store in lazy store - this.logger('($onlyOnce)', lazyStoreContent); - var list = Array.from(lazyStoreContent); - // should never have more than 1 - var ref = list[0]; - var payload = ref[0]; - var ctx = ref[1]; - var t = ref[2]; - if (t && t !== 'onlyOnce') { - throw new Error(("You are trying to register an event already been taken by other type: " + t)) - } - this.logger("($onlyOnce)", ("call run for " + evt)); - this.run(callback, payload, context || ctx); - // remove this evt from store - this.$off(evt); - } - return added; - }; - - /** - * This is a shorthand of $off + $on added in V1.5.0 - * @param {string} evt event name - * @param {function} callback to exeucte - * @param {object} [context = null] or pass a string as type - * @param {string} [type=on] what type of method to replace - * @return {} - */ - EventService.prototype.$replace = function $replace (evt, callback, context, type) { - if ( context === void 0 ) context = null; - if ( type === void 0 ) type = 'on'; - - if (this.validateType(type)) { - this.$off(evt); - var method = this['$' + type]; - this.logger("($replace)", evt, callback); - return Reflect.apply(method, this, [evt, callback, context]) - } - throw new Error((type + " is not supported!")) - }; - - /** - * trigger the event - * @param {string} evt name NOT allow array anymore! - * @param {mixed} [payload = []] pass to fn - * @param {object|string} [context = null] overwrite what stored - * @param {string} [type=false] if pass this then we need to add type to store too - * @return {number} if it has been execute how many times - */ - EventService.prototype.$trigger = function $trigger (evt , payload , context, type) { - if ( payload === void 0 ) payload = []; - if ( context === void 0 ) context = null; - if ( type === void 0 ) type = false; - - this.validateEvt(evt); - var found = 0; - // first check the normal store - var nStore = this.normalStore; - this.logger('($trigger)', 'normalStore', nStore); - if (nStore.has(evt)) { - // @1.8.0 to add the suspend queue - var added = this.$queue(evt, payload, context, type); - this.logger('($trigger)', evt, 'found; add to queue: ', added); - if (added === true) { - this.logger('($trigger)', evt, 'not 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; - }; - - /** - * 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 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) - } - }; - - /** - * 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; - - this.validateEvt(evt); - var stores = [ this.lazyStore, this.normalStore ]; - var found = false; - stores.forEach(function (store) { - if (store.has(evt)) { - found = true; - this$1.logger('($off)', evt); - store.delete(evt); - } - }); - return found; - }; - - /** - * return all the listener from the event - * @param {string} evtName event name - * @param {boolean} [full=false] if true then return the entire content - * @return {array|boolean} listerner(s) or false when not found - */ - EventService.prototype.$get = function $get (evt, full) { - if ( full === void 0 ) full = false; - - this.validateEvt(evt); - var store = this.normalStore; - if (store.has(evt)) { - return Array - .from(store.get(evt)) - .map( function (l) { - if (full) { - return l; - } - var key = l[0]; - var callback = l[1]; - return callback; - }) - } - return false; - }; - - /** - * store the return result from the run - * @param {*} value whatever return from callback - */ - prototypeAccessors.$done.set = function (value) { - this.logger('($done)', 'value: ', value); - if (this.keep) { - this.result.push(value); - } else { - this.result = value; - } - }; - - /** - * @TODO is there any real use with the keep prop? - * getter for $done - * @return {*} whatever last store result - */ - prototypeAccessors.$done.get = function () { - if (this.keep) { - this.logger('(get $done)', this.result); - return this.result[this.result.length - 1] - } - return this.result; - }; - - Object.defineProperties( EventService.prototype, prototypeAccessors ); - - return EventService; -}(NbEventServiceBase)); - -// 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 (NBEventService) { - function JsonqlWsEvt(logger) { - if (typeof logger !== 'function') { - throw new Error("Just die here the logger is not a function!") - } - // this ee will always come with the logger - // because we should take the ee from the configuration - NBEventService.call(this, { logger: logger }); - } - - if ( NBEventService ) JsonqlWsEvt.__proto__ = NBEventService; - JsonqlWsEvt.prototype = Object.create( NBEventService && NBEventService.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)); - -// mapping the resolver to their respective nsp - -/** - * Just make sure the object contain what we are looking for - * @param {object} opts configuration from checkOptions - * @return {object} the target content - */ -var getResolverList = function (contract) { - var result = extractSocketPart(contract); - if (result !== false) { - return result - } - throw new JsonqlResolverNotFoundError(MISSING_PROP_ERR) -}; - -/** - * process the contract first - * @param {object} opts configuration - * @return {object} sorted list - */ -function processContract(opts) { - var obj, obj$1; - - var contract = opts.contract; - var enableAuth = opts.enableAuth; - if (enableAuth) { - return groupByNamespace(contract) - } - return ( obj$1 = {}, obj$1[NSP_SET] = ( obj = {}, obj[JSONQL_PATH] = getResolverList(contract), obj ), obj$1[PUBLIC_NAMESPACE] = JSONQL_PATH, obj$1 ) -} - -// group all the small functions here -// we shouldn't do this anymore -var fixWss = function (url, serverType) { - // ws only allow ws:// path - if (serverType === JS_WS_NAME) { - return url.replace('http://', 'ws://') - } - return url -}; - -/** - * get a stock host name from browser - */ -var getHostName = function () { - try { - return [window.location.protocol, window.location.host].join('//') - } catch(e) { - throw new JsonqlValidationError(e) - } -}; - -/** - * Unbind the event - * @param {object} ee EventEmitter - * @param {string} namespace - * @return {void} - */ -var clearMainEmitEvt = function (ee, namespace) { - var nsps = toArray$1(namespace); - nsps.forEach(function (n) { - ee.$off(createEvt(n, EMIT_REPLY_TYPE)); - }); -}; - -// breaking it up further to share between methods - -/** - * break out to use in different places to handle the return from server - * @param {object} data from server - * @param {function} resolver NOT from promise - * @param {function} rejecter NOT from promise - * @return {void} nothing - */ -function respondHandler(data, resolver, rejecter) { - if (isObjectHasKey$1(data, ERROR_KEY)) { - // debugFn('-- rejecter called --', data[ERROR_KEY]) - rejecter(data[ERROR_KEY]); - } else if (isObjectHasKey$1(data, DATA_KEY)) { - // debugFn('-- resolver called --', data[DATA_KEY]) - resolver(data[DATA_KEY]); - } else { - // debugFn('-- UNKNOWN_RESULT --', data) - rejecter({message: UNKNOWN_RESULT, error: data}); - } -} - -// the actual trigger call method - -/** - * just wrapper - * @param {object} ee EventEmitter - * @param {string} namespace where this belongs - * @param {string} resolverName resolver - * @param {boolean} useCallbackStyle use on or not - * @param {array} args arguments - * @return {void} nothing - */ -function actionCall(ee, namespace, resolverName, useCallbackStyle, args) { - if ( args === void 0 ) args = []; - - var eventName = createEvt(namespace, EMIT_REPLY_TYPE); - var RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME; - // debugFn(`actionCall: ${eventName} --> ${resolverName}`, args) - ee.$trigger(eventName, [resolverName, toArray$1(args)]); - // once we trigger there is nothing return from the resolve - // @TODO if we need the next then call to have the result back - // then we need to listen to the event callback here as well - return new Promise(function (resolver, rejecter) { - ee.$on( - createEvt(namespace, resolverName, RESULT_SUBFIX), - function actionCallResultHandler(result) { - // debugFn(`got the first result`, result) - respondHandler(result, resolver, rejecter); - } - ); - }) -} - -// pairing with the server vesrion SEND_MSG_PROP_NAME -// last of the chain so only return the resolver (fn) -var setupSend = function (fn, ee, namespace, resolverName, params, useCallbackStyle) { return ( - objDefineProps(fn, SEND_MSG_PROP_NAME, function sendSetter(messagePayload) { - var ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME; - // debugFn('got payload for', messagePayload) - // @NOTE change from sync interface to async @ 1.0.0 - // this way we will able to catch all the error(s) - validateAsync$1(toArray$1(messagePayload), params.params, true) - .then(function (result) { - // here is the different we don't throw error instead we trigger onError - if (result[ERROR_KEY] && result[ERROR_KEY].length) { - // debugFn(`got ERROR_KEY`, result[ERROR_KEY]) - ee.$call( - createEvt(namespace, resolverName, ERROR_SUBFIX), - [new JsonqlValidationError(resolverName, result[ERROR_KEY])] - ); - } else { - // return it just for the catch to work - if any - return actionCall(ee, namespace, resolverName, useCallbackStyle, messagePayload) - } - }) - .catch(function (err) { - // debugFn(`error after validateAsync`, err) - ee.$call( - createEvt(namespace, resolverName, ERROR_SUBFIX), - [new JsonqlValidationError(resolverName, err)] - ); - }); - }, function sendGetter() { // add in 1.1.4 - return function sendGetterAction() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - return validateAsync$1(args, params.params, true) - .then(function (_args) { return actionCall(ee, namespace, resolverName, useCallbackStyle, _args); }) - .catch(finalCatch) - } - }) -); }; - -// @TODO using the obj.on syntax to do the same thing - -/** - * Add extra property to the resolver via the getter - * @param {function} fn the resolver itself - * @param {object} ee event emitter - * @param {string} namespace the namespace this belongs to - * @param {string} resolverName resolver namee - * @param {object} params from the contract - * @return {array} same as what goes in - */ -function setupCallbackApi(fn, ee, namespace, resolverName, params) { - return [ - injectToFn(fn, CB_FN_NAME, function(evtName, callback) { - if (isString$1(evtName) && isFunc(callback)) { - switch(evtName) { - case RESULT_PROP_NAME: - ee.$on( - createEvt(namespace, resolverName, ON_RESULT_PROP_NAME), - function resultHandler(result) { - respondHandler(result, callback, function (error) { - ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error); - }); - } - ); - break; - // register the handler for this message event - case MESSAGE_PROP_NAME: - ee.$only( - createEvt(namespace, resolverName, ON_MESSAGE_PROP_NAME), - function onMessageCallback(args) { - respondHandler(args, callback, function (error) { - ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error); - }); - } - ); - break; - case READY_PROP_NAME: - ee.$only( - createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), - callback - ); - break; - default: - ee.$trigger( - createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), - new JsonqlError(resolverName, ("Unknown event name " + evtName + "!")) - ); - } - } - }), - ee, - namespace, - resolverName, - params - ] -} - -// break up the original setup resolver method here - -/** - * The first one in the chain - * @return {array} - */ -var setupNamespace = function (fn, ee, namespace, resolverName, params, useCallbackStyle) { return [ - injectToFn(fn, MY_NAMESPACE, namespace), - ee, - namespace, - resolverName, - params, - useCallbackStyle -]; }; - -// onResult handler -var setupOnResult = function (fn, ee, namespace, resolverName, params, useCallbackStyle) { return [ - objDefineProps(fn, ON_RESULT_PROP_NAME, function(resultCallback) { - if (isFunc(resultCallback)) { - ee.$on( - createEvt(namespace, resolverName, ON_RESULT_PROP_NAME), - function resultHandler(result) { - respondHandler(result, resultCallback, function (error) { - ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error); - }); - } - ); - } - }), - ee, - namespace, - resolverName, - params, - useCallbackStyle -]; }; - -// we do need to add the send prop back because it's the only way to deal with -// bi-directional data stream -var setupOnMessage = function (fn, ee, namespace, resolverName, params, useCallbackStyle) { return [ - objDefineProps(fn, ON_MESSAGE_PROP_NAME, function(messageCallback) { - // we expect this to be a function - if (isFunc(messageCallback)) { - // did that add to the callback - var onMessageCallback = function (args) { - respondHandler(args, messageCallback, function (error) { - ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error); - }); - }; - // register the handler for this message event - ee.$only(createEvt(namespace, resolverName, ON_MESSAGE_PROP_NAME), onMessageCallback); - } - }), - ee, - namespace, - resolverName, - params, - useCallbackStyle -]; }; - -// add an ON_ERROR_PROP_NAME handler -var setupOnError = function (fn, ee, namespace, resolverName, params, useCallbackStyle) { return [ - objDefineProps(fn, ON_ERROR_PROP_NAME, function(resolverErrorHandler) { - if (isFunc(resolverErrorHandler)) { - // please note ON_ERROR_PROP_NAME can add multiple listners - ee.$only(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), resolverErrorHandler); - } - }), - ee, - namespace, - resolverName, - params, - useCallbackStyle -]; }; - -/** - * Add extra property to the resolver - * @param {string} namespace where this belongs - * @param {string} resolverName name as event name - * @param {object} params from contract - * @param {function} fn resolver function - * @param {object} ee EventEmitter - * @param {boolean} useCallbackStyle new callback style - * @return {function} resolver - */ -function setupResolver(namespace, resolverName, params, fn, ee, useCallbackStyle) { - // also need to setup a getter to get back the namespace of this resolver - var args = [setupNamespace]; - useCallbackStyle ? args.push(setupCallbackApi) : args.push(setupOnResult, setupOnMessage, setupOnError); - args.push(setupSend); - // get the executor - var executor = Reflect.apply(chainFns, null, args); - - return Reflect.apply(executor, null, [fn, ee, namespace, resolverName, params, useCallbackStyle]) -} - -// put all the resolver related methods here to make it more clear - -/** - * create the actual function to send message to server - * @param {object} ee EventEmitter instance - * @param {string} namespace this resolver end point - * @param {string} resolverName name of resolver as event name - * @param {object} params from contract - * @param {boolean} useCallbackStyle on style or not - * @return {function} resolver - */ -function createResolver(ee, namespace, resolverName, params, useCallbackStyle) { - // note we pass the new withResult=true option - return function() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - return validateAsync$1(args, params.params, true) - .then(function (_args) { return actionCall(ee, namespace, resolverName, useCallbackStyle, _args); }) - .catch(finalCatch) - } -} - -/** - * The problem is the namespace can have more than one - * and we only have on onError message - * @param {object} obj the client itself - * @param {object} ee Event Emitter - * @param {object} nspSet namespace keys - * @param {boolean} useCallbackStyle use cb or not - * @return {object} obj with onError prop - */ -function createNamespaceErrorHandler(obj, ee, nspSet) { - // using the onError as name - // @TODO we should follow the convention earlier - // make this a setter for the obj itself - return objDefineProps(obj, ON_ERROR_PROP_NAME, function namespaceErrorCallbackHandler(namespaceErrorHandler) { - if (isFunc(namespaceErrorHandler)) { - // please note ON_ERROR_PROP_NAME can add multiple listners - for (var namespace in nspSet) { - // 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_PROP_NAME), namespaceErrorHandler); - } - } - }) -} - -/** - * This event will fire when the socket.io.on('connection') and ws.onopen - * @param {object} obj the client itself - * @param {object} ee Event Emitter - * @param {object} nspSet namespace keys - * @return {object} obj with onReady prop - */ -function createOnReadyhandler(obj, ee, nspSet) { - return objDefineProps(obj, ON_READY_PROP_NAME, function onReadyCallbackHandler(onReadyCallback) { - if (isFunc(onReadyCallback)) { - // reduce it down to just one flat level - ee.$on(ON_READY_PROP_NAME, onReadyCallback); - } - }) -} - -/** - * This event will fire when the socket.io.on('connection') and ws.onopen - * Plus this will check if it's the private namespace that fired the event - * @param {object} obj the client itself - * @param {object} ee Event Emitter - * @param {object} opts configuration - * @return {object} obj with onLogin prop - */ -function createOnLoginhandler(obj, ee, opts) { - if (opts.enableAuth) { - return objDefineProps(obj, ON_LOGIN_PROP_NAME, function onLoginCallbackHandler(onLoginCallback) { - if (isFunc(onLoginCallback)) { - // only one callback can registered with it, TBC - ee.$only(ON_LOGIN_PROP_NAME, onLoginCallback); - } - }) - } - // just skip it - return obj -} - -/** - * when useCallbackStyle=true use this instead of the above method - * @param {object} obj the base object to attach to - * @param {object} ee EventEmitter - * @param {object} nspSet the map - * @param {object} opts configuration - * @return {object} obj - */ -function createCallbackHandler(obj, ee, nspSet, opts) { - return injectToFn(obj, CB_FN_NAME, function onHandler(evtName, callback) { - if (isString$1(evtName) && isFunc(callback)) { - switch (evtName) { - case ERROR_PROP_NAME: - for (var namespace in nspSet) { - // 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, ERROR_PROP_NAME), callback); - } - break; - case LOGIN_PROP_NAME: // @TODO should only available when enableAuth=true - ee.$only(LOGIN_PROP_NAME, callback); - break; - case READY_PROP_NAME: - ee.$on(READY_PROP_NAME, callback); - break; - default: - ee.$trigger(ERROR_PROP_NAME, new JsonqlError(CB_FN_NAME, ("Unknown event name " + evtName + "!"))); - } - } - // @TODO need to issue another error here! - }) -} - -// take out from the resolver-methods - -/** - * @TODO this is now become unnecessary because the login is a slave to the - * http-client - but keep this for now and see what we want to do with it later - * break out from createAuthMethods to allow chaining call - * @param {object} obj the main client object - * @param {object} ee event emitter - * @param {object} opts configuration - * @return {array} modified input - */ -var setupLoginHandler = function (obj, ee, opts) { return [ - injectToFn(obj, opts.loginHandlerName, function loginHandler(token) { - if (token && isString$1(token)) { - return ee.$trigger(LOGIN_EVENT_NAME, [token]) - } - // should trigger a global error instead @TODO - throw new JsonqlValidationError(opts.loginHandlerName, ("Unexpected token " + token)) - }), - ee, - opts -]; }; - -/** - * break out from createAuthMethods to allow chaining call - final in chain - * @param {object} obj the main client object - * @param {object} ee event emitter - * @param {object} opts configuration - * @return {object} the modified obj - */ -var setupLogoutHandler = function (obj, ee, opts) { return ( - injectToFn(obj, opts.logoutHandlerName, function logoutHandler() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - ee.$trigger(LOGOUT_EVENT_NAME, args); - }) -); }; - -/** - * Create auth related methods - * @param {object} obj the client itself - * @param {object} ee Event Emitter - * @param {object} opts configuration - * @return {object} obj with auth methods if any - */ -function createAuthMethods(obj, ee, opts) { - if (opts.enableAuth) { - return chainFns(setupLoginHandler, setupLogoutHandler)(obj, ee, opts) - } - return obj -} - -// resolvers generator - -/** - * step one get the obj map with the namespace - * @param {object} opts configuration - * @param {object} nspMap resolvers index by their namespace - * @param {object} ee EventEmitter - * @return {promise} resolve the obj mapped, and start the chain - */ -function getMappedObj(opts, nspMap, ee) { - var obj = {}; - // let resolverNames = []; - var nspSet = nspMap.nspSet; - var useCallbackStyle = opts.useCallbackStyle; // @1.2.1 - for (var namespace in nspSet) { - var list = nspSet[namespace]; - for (var resolverName in list) { - // resolverNames.push(resolverName) - var params = list[resolverName]; - var fn = createResolver(ee, namespace, resolverName, params, useCallbackStyle); - // this should set as a getter therefore can not be overwrite by accident - // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee) - obj = injectToFn(obj, resolverName, setupResolver(namespace, resolverName, params, fn, ee, useCallbackStyle)); - } - } - // move this two method down to helpers - // we want these methods visible in debug or console.log - obj.devHelpers = { - // this is a helper method for the developer to know the namespace inside - getNsp: function () { return Object.keys(nspSet); }, - // simple get version trick - getVer: function () { return opts.version || 'NOT SET'; } - // not really necessary because the dev can query the contract - // getResolverNames: () => resolverNames - }; - // resolve the obj to start the chain - // chain the result to allow the chain processing - return Promise.resolve(obj) -} - -/** - * prepare the methods - * @param {object} opts configuration - * @param {object} nspMap resolvers index by their namespace - * @param {object} ee EventEmitter - * @return {object} of resolvers - * @public - */ -function generator(opts, nspMap, ee) { - var nspSet = nspMap.nspSet; - var useCallbackStyle = opts.useCallbackStyle; - var enableAuth = opts.enableAuth; - var args = [getMappedObj]; - if (useCallbackStyle) { - args.push(function (obj) { return createCallbackHandler(obj, ee, nspSet); }); - } else { - args.push( - function (obj1) { return createNamespaceErrorHandler(obj1, ee, nspSet); }, - function (obj2) { return createOnReadyhandler(obj2, ee); } - ); - if (enableAuth) { - args.push(function (obj3) { return createOnLoginhandler(obj3, ee, opts); }); - } - } - // this only apply to when enableAuth = true - if (enableAuth) { - args.push(function (obj4) { return createAuthMethods(obj4, ee, opts); }); - } - // run it - var executor = Reflect.apply(chainProcessPromises, null, args); - return executor(opts, nspMap, ee) -} - -var obj, obj$1; -var AVAILABLE_METHODS = [IO_ROUNDTRIP_LOGIN, IO_HANDSHAKE_LOGIN]; - -var wsCoreDefaultOptions = { - useCallbackStyle: createConfig$1(false, [BOOLEAN_TYPE]), - loginHandlerName: createConfig$1(ISSUER_NAME, [STRING_TYPE]), - logoutHandlerName: createConfig$1(LOGOUT_NAME, [STRING_TYPE]), - // this is for socket.io - loginMethod: createConfig$1(IO_HANDSHAKE_LOGIN, [STRING_TYPE], ( obj = {}, obj[ENUM_KEY] = AVAILABLE_METHODS, obj )), - // we will use this for determine the socket.io client type as well - @TODO remove or rename - useJwt: createConfig$1(true, [BOOLEAN_TYPE, STRING_TYPE]), - // this is going to replace the use of useJwt === string next - authStrKey: createConfig$1(null, [STRING_TYPE]), - hostname: createConfig$1(false, [STRING_TYPE]), - namespace: createConfig$1(JSONQL_PATH, [STRING_TYPE]), - wsOptions: createConfig$1({}, [OBJECT_TYPE]), - // make this null as default don't set this here, only set in the down stream - // serverType: createConfig(null, [STRING_TYPE], {[ENUM_KEY]: AVAILABLE_SERVERS}), - // we require the contract already generated and pass here - contract: createConfig$1({}, [OBJECT_TYPE], ( obj$1 = {}, obj$1[CHECKER_KEY] = isContract, obj$1 )), - enableAuth: createConfig$1(false, [BOOLEAN_TYPE]), - token: createConfig$1(false, [STRING_TYPE]) -}; - -// constant props -var wsCoreConstProps = { - // contract: null, - eventEmitter: null, - // we unify the two different client into one now - // only expect different parameter - nspClient: null, - nspAuthClient: null, - // contructed path - wssPath: '' -}; - -// create options - -/** - * wrapper method to check this already did the pre check - * @param {object} config user supply config - * @param {object} defaultOptions for checking - * @param {object} constProps user supply const props - * @return {promise} resolve to the checked opitons - */ -function checkOptionsWrapper(config, defaultOptions, constProps) { - var wsConstProps = Object.assign(wsCoreConstProps, constProps); - var defaultCheckOptions = Object.assign(wsCoreDefaultOptions, defaultOptions); - /* - const fn = postConfigCheck(checkMap, constProps, checkConfig) - return fn(config) - */ - return checkConfigAsync(config, defaultCheckOptions, wsConstProps) -} - -/** - * Taking the then part from the method below - * @param {object} opts - * @return {promise} opts all done - */ -function postWsOptions(opts) { - return Promise.resolve(opts) - .then(function (opts) { - if (!opts.hostname) { - opts.hostname = getHostName(); - } - // @TODO the contract now will supply the namespace information - // and we need to use that to group the namespace call - opts.wssPath = fixWss([opts.hostname, opts.namespace].join('/'), opts.serverType); - // debug('CONFIGURATION OPTIONS', opts) - return opts - }) -} - -/** - * check the configuration - * @param {object} config user supplied configuration - * @param {object} defaultOptions the check map - * @param {object} constProps developer supplied configuration - * @return {object} after checked - */ -function checkWsCoreOptions(config, defaultOptions, constProps) { - return checkOptionsWrapper(config, defaultOptions, constProps) - .then(postWsOptions) -} - -// the top level API - -/** - * @TODO remove this implmenetation once the test is done - */ -var dummyLogger = function () { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - Reflect.apply(console.info, console, ['[jsonql-ws-client-core]' ].concat( args)); -}; - -/** - * 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; - log('CHECKED_KEY', opts[CHECKED_KEY]); - if (eventEmitter) { - log("eventEmitter is:", eventEmitter.name); - return eventEmitter - } - log("Create a new Event Emitter"); - return new JsonqlWsEvt( opts.log ) -}; - -/** - * 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') { - opts.log = dummyLogger; - } - opts.log('--- wsClientCore config opts ---', opts); - return opts -}; - -/** - * 0.5.0 we break up the wsClientCore in two parts one without the config check - * @param {function} socketClientResolver - * @param {object} config the already checked config - */ -function wsClientCoreAction(socketClientResolver, config) { - return Promise.resolve(config) - .then(getLogFn) - .then(function (opts) { return ({ - opts: opts, - nspMap: processContract(opts), - ee: getEventEmitter(opts) - }); }) - .then( - function (ref) { - var opts = ref.opts; - var nspMap = ref.nspMap; - var ee = ref.ee; - - return socketClientResolver(opts, nspMap, ee); - } - ) - .then( - function (ref) { - var opts = ref.opts; - var nspMap = ref.nspMap; - var ee = ref.ee; - - return generator(opts, nspMap, ee); - } - ) - .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} socketClientResolver this is the one method export by various clients - * @param {object} [defaultOptions={}] 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 {object} the wsClient instance with all the available API - */ -function wsClientCore(socketClientResolver, defaultOptions, constProps) { - if ( defaultOptions === void 0 ) defaultOptions = {}; - if ( constProps === void 0 ) constProps = {}; - - // we need to inject property to this client later - // therefore we need to do it this way - return function (config) { - if ( config === void 0 ) config = {}; - - return ( - checkWsCoreOptions(config, defaultOptions, constProps) - .then(function (opts) { return wsClientCoreAction(socketClientResolver, opts); }) - ); - } - -} - -// jsonql-ws-core takes over the check configuration -// constant props -var wsClientConstProps = { - version: 'version: 1.1.0 module: cjs', // will get replace - serverType: JS_WS_NAME -}; - -var wsClientAppProps = {}; - -// pass the different type of ws to generate the client -/** - * WebSocket is strict about the path, therefore we need to make sure before it goes in - * @param {string} url input url - * @return {string} url with correct path name - */ -var fixWss$1 = function (url) { - var uri = url.toLowerCase(); - if (uri.indexOf('http') > -1) { - if (uri.indexOf('https') > -1) { - return uri.replace('https', 'wss') - } - return uri.replace('http', 'ws') - } - return uri -}; - -/** - * The bug was in the wsOptions where ws doesn't need it but socket.io do - * therefore the object was pass as second parameter! - * @param {object} WebSocket the client or node version of ws - * @param {boolean} auth if it's auth then 3 param or just one - */ -function createWsClient(WebSocket, auth) { - if ( auth === void 0 ) auth = false; - - if (auth === false) { - return function createWsClientHandler(url) { - return new WebSocket(fixWss$1(url)) - } - } - - /** - * Create a client with auth token - * @param {string} url start with ws:// @TODO check this? - * @param {string} token the jwt token - * @return {object} ws instance - */ - return function createWsAuthClientHandler(url, token) { - var ws_url = fixWss$1(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 - } - } -} - -// since both the ws and io version are -// pre-defined in the client-generator -// and this one will have the same parameters -// and the callback is identical - -/** - * wrapper method to create a nsp without login - * @param {string|boolean} namespace namespace url could be false - * @param {object} opts configuration - * @return {object} ws client instance - */ -function createNspClient(namespace, opts) { - var hostname = opts.hostname; - var wssPath = opts.wssPath; - var wsOptions = opts.wsOptions; - var nspClient = opts.nspClient; - var url = namespace ? [hostname, namespace].join('/') : wssPath; - return nspClient(url, wsOptions) -} - -/** - * wrapper method to create a nsp with token auth - * @param {string} namespace namespace url - * @param {object} opts configuration - * @return {object} ws client instance - */ -function createNspAuthClient(namespace, opts) { - var hostname = opts.hostname; - var wssPath = opts.wssPath; - var token = opts.token; - var wsOptions = opts.wsOptions; - var nspAuthClient = opts.nspAuthClient; - var url = namespace ? [hostname, namespace].join('/') : wssPath; - if (token && typeof token !== 'string') { - throw new Error(("Expect token to be string, but got " + token)) - } - return nspAuthClient(url, token, wsOptions) -} - -// 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 - * @param {object} opts configuration - * @return {void} - */ -function triggerNamespacesOnError(ee, namespaces, message, opts) { - if ( opts === void 0 ) opts = {}; - - var useCallbackStyle = opts.useCallbackStyle; - var ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME; - namespaces.forEach( function (namespace) { - ee.$call(createEvt(namespace, ERROR_SUBFIX), [{ message: message, namespace: namespace }]); - }); -} - -// This is share between different clients so we export it - -/** - * A fake ee handler - * @param {string} namespace nsp - * @param {object} ee EventEmitter - * @param {object} opts configuration - * @return {void} - */ -var notLoginWsHandler = function (namespace, ee, opts) { - var useCallbackStyle = opts.useCallbackStyle; - var log = opts.log; - var ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME; - var RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME; - ee.$only( - createEvt(namespace, EMIT_EVT), - function notLoginHandlerCallback(resolverName, args) { - - log('[notLoginHandler] 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, ERROR_SUBFIX), [error]); - // also trigger the result handler, but wrap inside the error key - ee.$call(createEvt(namespace, resolverName, RESULT_SUBFIX), [{ 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 -); }; - -/** - * centralize all the comm in one place - * @param {object} opts configuration - * @param {array} namespaces namespace(s) - * @param {object} ee Event Emitter instance - * @param {function} bindWsHandler binding the ee to ws --> this is the core bit - * @param {array} namespaces array of namespace available - * @param {object} nsps namespaced nsp - * @return {void} nothing - */ -function clientEventHandler(opts, nspMap, ee, bindWsHandler, namespaces, nsps) { - // @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 log = opts.log; - // 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 a waterfall here to make sure - // one is execute then the other - namespaces.forEach(function (namespace) { - isPrivate = privateNamespace === namespace; - if (nsps[namespace]) { - log('[call bindWsHandler]', isPrivate, namespace); - var args = [namespace, nsps[namespace], ee, isPrivate, opts]; - if (opts.serverType === SOCKET_IO) { - var nspSet = nspMap.nspSet; - args.push(nspSet[namespace]); - } - Reflect.apply(bindWsHandler, null, args); - } else { - // a dummy placeholder - notLoginWsHandler(namespace, ee, opts); - } - }); - // this will be available regardless enableAuth - // because the server can log the client out - ee.$on(LOGOUT_EVENT_NAME, function logoutEvtHandler() { - log('LOGOUT_EVENT_NAME'); - // disconnect(nsps, opts.serverType) - // we need to issue error to all the namespace onError handler - triggerNamespacesOnError(ee, namespaces, LOGOUT_EVENT_NAME); - // rebind all of the handler to the fake one - namespaces.forEach( function (namespace) { - clearMainEmitEvt(ee, namespace); - // clear out the nsp - nsps[namespace] = false; - // add a NOT LOGIN error if call - notLoginWsHandler(namespace, ee, opts); - }); - }); -} - -// take the ws reply data for use - -var keys$1 = [ WS_REPLY_TYPE, WS_EVT_NAME, WS_DATA_NAME ]; - -/** - * @param {object} payload should be string when reply but could be transformed - * @return {boolean} true is OK - */ -var isWsReply = function (payload) { - var data = payload.data; - if (data) { - var result = keys$1.filter(function (key) { return isObjectHasKey$1(data, key); }); - return (result.length === keys$1.length) ? data : false - } - return false -}; - -/** - * @param {object} payload This is the entire ws Event Object - * @return {object} false on failed - */ -var extractWsPayload = function (payload) { - var data = payload.data; - var json = isString$1(data) ? JSON.parse(data) : data; - var fdata; - if ((fdata = isWsReply(json)) !== false) { - return { - resolverName: fdata[WS_EVT_NAME], - data: fdata[WS_DATA_NAME], - type: fdata[WS_REPLY_TYPE] - } - } - throw new JsonqlError('payload can not be decoded', payload) -}; - -// the WebSocket main handler - - -/** - * under extremely circumstances we might not even have a resolverName, then - * we issue a global error for the developer to catch it - * @param {object} ee event emitter - * @param {string} namespace nsp - * @param {string} resolverName resolver - * @param {object} json decoded payload or error object - * @param {string} ERROR_EVT_NAME the error event name - * @return {undefined} nothing return - */ -var errorTypeHandler = function (ee, namespace, resolverName, json, ERROR_EVT_NAME) { - var evt = [namespace]; - if (resolverName) { - evt.push(resolverName); - } - evt.push(ERROR_EVT_NAME); - var evtName = Reflect.apply(createEvt, null, evt); - // test if there is a data field - var payload = json.data || json; - ee.$trigger(evtName, [payload]); -}; - -/** - * Binding the even to socket normally - * @param {string} namespace - * @param {object} ws the nsp - * @param {object} ee EventEmitter - * @param {boolean} isPrivate to id if this namespace is private or not - * @param {object} opts configuration - * @return {object} promise resolve after the onopen event - */ -function wsMainHandler(namespace, ws, ee, isPrivate, opts) { - var useCallbackStyle = opts.useCallbackStyle; - var log = opts.log; - - log("wsMainHandler log test"); - - var READY_EVT_NAME = useCallbackStyle ? READY_PROP_NAME : ON_READY_PROP_NAME; - var LOGIN_EVT_NAME = useCallbackStyle ? LOGIN_PROP_NAME : ON_LOGIN_PROP_NAME; - var MESSAGE_EVT_NAME = useCallbackStyle ? MESSAGE_PROP_NAME : ON_MESSAGE_PROP_NAME; - var RESULT_EVT_NAME = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME; - var ERROR_EVT_NAME = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME; - // connection open - ws.onopen = function onOpenCallback() { - log('ws.onopen listened'); - // we just call the onReady - ee.$call(READY_EVT_NAME, namespace); - // need an extra parameter here to id the private nsp - if (isPrivate) { - log(("isPrivate and fire the " + LOGIN_EVT_NAME)); - ee.$call(LOGIN_EVT_NAME, namespace); - } - // add listener only after the open is called - ee.$only( - createEvt(namespace, EMIT_REPLY_TYPE), - function wsMainOnEvtHandler(resolverName, args) { - log('calling server', resolverName, args); - ws.send( - createQueryStr(resolverName, args) - ); - } - ); - }; - - // reply - // If we change it to the event callback style - // then the payload will just be the payload and fucks up the extractWsPayload call @TODO - ws.onmessage = function onMessageCallback(payload) { - // console.log(`on.message`, typeof payload, payload) - try { - var json = extractWsPayload(payload); - var resolverName = json.resolverName; - var type = json.type; - log('Hear from server', type, json); - switch (type) { - case EMIT_REPLY_TYPE: - var e1 = createEvt(namespace, resolverName, MESSAGE_EVT_NAME); - var r = ee.$trigger(e1, [json]); - log("EMIT_REPLY_TYPE", e1, r); - break; - case ACKNOWLEDGE_REPLY_TYPE: - var e2 = createEvt(namespace, resolverName, RESULT_EVT_NAME); - var x = ee.$trigger(e2, [json]); - // log(`ACKNOWLEDGE_REPLY_TYPE`, e2, json) - break; - case ERROR_TYPE: - // this is handled error and we won't throw it - // we need to extract the error from json - log("ERROR_TYPE"); - errorTypeHandler(ee, namespace, resolverName, json, ERROR_EVT_NAME); - break; - // @TODO there should be an error type instead of roll into the other two types? TBC - default: - // if this happen then we should throw it and halt the operation all together - log('Unhandled event!', json); - errorTypeHandler(ee, namespace, resolverName, json, ERROR_EVT_NAME); - // let error = {error: {'message': 'Unhandled event!', type}}; - // ee.$trigger(createEvt(namespace, resolverName, ON_RESULT_PROP_NAME), [error]) - } - } catch(e) { - console.error("ws.onmessage error", e); - errorTypeHandler(ee, namespace, false, e, ERROR_EVT_NAME); - } - }; - // when the server close the connection - ws.onclose = function onCloseCallback() { - log('ws.onclose callback'); - // @TODO what to do with this - // ee.$trigger(LOGOUT_EVENT_NAME, [namespace]) - }; - // listen to the LOGOUT_EVENT_NAME - ee.$on(LOGOUT_EVENT_NAME, function closeEvtHandler() { - try { - log('terminate ws connection'); - ws.terminate(); - } catch(e) { - console.error('ws.terminate error', e); - } - }); -} - -// actually binding the event client to the socket client - -/** - * 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 createNsps = function(opts, nspMap, token) { - var nspSet = nspMap.nspSet; - var publicNamespace = nspMap.publicNamespace; - var login = false; - var namespaces = []; - var nsps = {}; - // first we need to binding all the events handler - if (opts.enableAuth) { // && opts.useJwt - login = true; // just saying we need to listen to login event - namespaces = getNamespaceInOrder(nspSet, publicNamespace); - nsps = namespaces.map(function (namespace, i) { - var obj, obj$1, obj$2; - - if (i === 0) { - if (token) { - opts.token = token; - // console.log('create createNspAuthClient at run time', opts) - 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); }, {}); - } else { - var namespace = getNameFromPayload(nspSet); - namespaces.push(namespace); - // standard without login - // the stock version should not have a namespace - nsps[namespace] = createNspClient(false, opts); - } - // return - return { nsps: nsps, namespaces: namespaces, login: login } -}; - -/** - * create a ws client - * @param {object} opts configuration - * @param {object} nspMap namespace with resolvers - * @param {object} ee EventEmitter to pass through - * @return {object} what comes in what goes out - */ -function createClient(opts, nspMap, ee) { - // arguments that don't change - var args = [opts, nspMap, ee, wsMainHandler]; - // now create the nsps - var token = opts.token; - var log = opts.log; - var ref = createNsps(opts, nspMap, token); - var nsps = ref.nsps; - var namespaces = ref.namespaces; - var login = ref.login; - // 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.concat([namespaces, nsps])); - // setup listener - if (login) { - ee.$only(LOGIN_EVENT_NAME, function loginEventHandler(tokenLater) { - - log('createClient LOGIN_EVENT_NAME'); - - // debugFn(`LOGIN_EVENT_NAME called with token:`, tokenLater) - // @BUG this keep causing an "Disconnect call failed TypeError: Cannot read property 'readyState' of null" - // I think that is because it's not login then it can not be disconnect - // how do we track this state globally - // disconnect(nsps, JS_WS_NAME) - - // @TODO should we trigger error on this one? - // triggerNamespacesOnError(ee, namespaces, LOGIN_EVENT_NAME) - clearMainEmitEvt(ee, namespaces); - // console.log('LOGIN_EVENT_NAME', token) - var newNsps = createNsps(opts, nspMap, tokenLater); - // rebind it - Reflect.apply( - clientEventHandler, - null, - args.concat([newNsps.namespaces, newNsps.nsps]) - ); - }); - } - // return what input - return { opts: opts, nspMap: nspMap, ee: ee } -} - -// share method to create the wsClientResolver - -/** - * combine the create client resolver - * @param {object} ws the different WebSocket module - * @return {function} the wsClientResolver - */ -function createClientResolver(ws) { - var client = createWsClient(ws); - var authClient = createWsClient(ws, true); - /** - * wsClientResolver - * @param {object} opts configuration - * @param {object} nspMap from the contract - * @param {object} ee instance of the eventEmitter - * @return {object} passing the same 3 input out with additional in the opts - */ - return function(opts, nspMap, ee) { - opts.nspClient = client; - opts.nspAuthClient = authClient; - // @1.0.7 remove later once everything fixed - var log = opts.log; - if (log && typeof log === 'function') { - log('@jsonql/ws ee', ee.name); - log('@jsonql/ws createClientResolver', opts); - } - // console.log(`contract`, opts.contract) - return createClient(opts, nspMap, ee) - } -} - -// this will be the news style interface that will pass to the jsonql-ws-client - -/** - * @param {object} opts configuration - * @param {object} nspMap from the contract - * @param {object} ee instance of the eventEmitter - * @return {object} passing the same 3 input out with additional in the opts - */ -var wsClientResolver = createClientResolver(WebSocket); - -// this is the module entry point for node - -// export back the function and that's it -function wsBrowserClient(config, constProps) { - if ( config === void 0 ) config = {}; - if ( constProps === void 0 ) constProps = {}; - - var initMethod = wsClientCore(wsClientResolver, wsClientAppProps, Object.assign(wsClientConstProps, constProps)); - return initMethod(config) -} - -module.exports = wsBrowserClient; +"use strict";var t,r=(t=require("ws"))&&"object"==typeof t&&"default"in t?t.default:t,e=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 406},e.name.get=function(){return"Jsonql406Error"},Object.defineProperties(r,e),r}(Error),n=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 500},e.name.get=function(){return"Jsonql500Error"},Object.defineProperties(r,e),r}(Error),o=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 403},e.name.get=function(){return"JsonqlForbiddenError"},Object.defineProperties(r,e),r}(Error),a=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 401},e.name.get=function(){return"JsonqlAuthorisationError"},Object.defineProperties(r,e),r}(Error),i=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 401},e.name.get=function(){return"JsonqlContractAuthError"},Object.defineProperties(r,e),r}(Error),u=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 500},e.name.get=function(){return"JsonqlResolverAppError"},Object.defineProperties(r,e),r}(Error),c=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 404},e.name.get=function(){return"JsonqlResolverNotFoundError"},Object.defineProperties(r,e),r}(Error),s=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlEnumError"},Object.defineProperties(r,e),r}(Error),f=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlTypeError"},Object.defineProperties(r,e),r}(Error),l=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlCheckerError"},Object.defineProperties(r,e),r}(Error),p=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(r,e),r}(Error),h=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0},statusCode:{configurable:!0}};return e.name.get=function(){return"JsonqlError"},e.statusCode.get=function(){return-1},Object.defineProperties(r,e),r}(Error),v=function(t){function r(e,n){t.call(this,n),this.statusCode=e,this.className=r.name}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlServerError"},Object.defineProperties(r,e),r}(Error);function g(t){if(Array.isArray(t))throw new p("",t);var r=t.message||"No message",g=t.detail||t;switch(!0){case t instanceof e:throw new e(r,g);case t instanceof n:throw new n(r,g);case t instanceof o:throw new o(r,g);case t instanceof a:throw new a(r,g);case t instanceof i:throw new i(r,g);case t instanceof u:throw new u(r,g);case t instanceof c:throw new c(r,g);case t instanceof s:throw new s(r,g);case t instanceof f:throw new f(r,g);case t instanceof l:throw new l(r,g);case t instanceof p:throw new p(r,g);case t instanceof v:throw new v(r,g);default:throw new h(r,g)}}var y="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},d="object"==typeof y&&y&&y.Object===Object&&y,b="object"==typeof self&&self&&self.Object===Object&&self,_=d||b||Function("return this")(),m=_.Symbol;function w(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 a=Array(o);++n-1;);return e}(n,o),function(t,r){for(var e=t.length;e--&&M(r,t[e],0)>-1;);return e}(n,o)+1).join("")}var Z=function(t){return!!j(t)||null!=t&&""!==X(t)};function tt(t){return function(t){return"number"==typeof t||P(t)&&"[object Number]"==A(t)}(t)&&t!=+t}function rt(t){return"string"==typeof t||!j(t)&&P(t)&&"[object String]"==A(t)}var et=function(t){return!rt(t)&&!tt(parseFloat(t))},nt=function(t){return""!==X(t)&&rt(t)},ot=function(t){return null!=t&&"boolean"==typeof t},at=function(t,r){return void 0===r&&(r=!0),void 0!==t&&""!==t&&""!==X(t)&&(!1===r||!0===r&&null!==t)},it=function(t){switch(t){case"number":return et;case"string":return nt;case"boolean":return ot;default:return at}},ut=function(t,r){return void 0===r&&(r=""),!!j(t)&&(""===r||""===X(r)||!(t.filter((function(t){return!it(r)(t)})).length>0))},ct=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var r=t.replace("array.<","").replace(">","");return r.indexOf("|")?r.split("|"):[r]}return!1},st=function(t,r){var e=t.arg;return r.length>1?!e.filter((function(t){return!(r.length>r.filter((function(r){return!it(r)(t)})).length)})).length:r.length>r.filter((function(t){return!ut(e,t)})).length};function ft(t,r){return function(e){return t(r(e))}}var lt=ft(Object.getPrototypeOf,Object),pt=Function.prototype,ht=Object.prototype,vt=pt.toString,gt=ht.hasOwnProperty,yt=vt.call(Object);function dt(t){if(!P(t)||"[object Object]"!=A(t))return!1;var r=lt(t);if(null===r)return!0;var e=gt.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&vt.call(e)==yt}var bt,_t=function(t,r,e){for(var n=-1,o=Object(t),a=e(t),i=a.length;i--;){var u=a[bt?i:++n];if(!1===r(o[u],u,o))break}return t};function mt(t){return P(t)&&"[object Arguments]"==A(t)}var wt=Object.prototype,jt=wt.hasOwnProperty,Ot=wt.propertyIsEnumerable,St=mt(function(){return arguments}())?mt:function(t){return P(t)&&jt.call(t,"callee")&&!Ot.call(t,"callee")};var kt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Et=kt&&"object"==typeof module&&module&&!module.nodeType&&module,$t=Et&&Et.exports===kt?_.Buffer:void 0,Tt=($t?$t.isBuffer:void 0)||function(){return!1},At=/^(?:0|[1-9]\d*)$/;function Pt(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&At.test(t))&&t>-1&&t%1==0&&t-1&&t%1==0&&t<=9007199254740991}var zt={};zt["[object Float32Array]"]=zt["[object Float64Array]"]=zt["[object Int8Array]"]=zt["[object Int16Array]"]=zt["[object Int32Array]"]=zt["[object Uint8Array]"]=zt["[object Uint8ClampedArray]"]=zt["[object Uint16Array]"]=zt["[object Uint32Array]"]=!0,zt["[object Arguments]"]=zt["[object Array]"]=zt["[object ArrayBuffer]"]=zt["[object Boolean]"]=zt["[object DataView]"]=zt["[object Date]"]=zt["[object Error]"]=zt["[object Function]"]=zt["[object Map]"]=zt["[object Number]"]=zt["[object Object]"]=zt["[object RegExp]"]=zt["[object Set]"]=zt["[object String]"]=zt["[object WeakMap]"]=!1;var Ct,xt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Rt=xt&&"object"==typeof module&&module&&!module.nodeType&&module,qt=Rt&&Rt.exports===xt&&d.process,Mt=function(){try{var t=Rt&&Rt.require&&Rt.require("util").types;return t||qt&&qt.binding&&qt.binding("util")}catch(t){}}(),Ft=Mt&&Mt.isTypedArray,Lt=Ft?(Ct=Ft,function(t){return Ct(t)}):function(t){return P(t)&&Nt(t.length)&&!!zt[A(t)]},Jt=Object.prototype.hasOwnProperty;function It(t,r){var e=j(t),n=!e&&St(t),o=!e&&!n&&Tt(t),a=!e&&!n&&!o&&Lt(t),i=e||n||o||a,u=i?function(t,r){for(var e=-1,n=Array(t);++e-1},tr.prototype.set=function(t,r){var e=this.__data__,n=Xt(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};var rr,er=_["__core-js_shared__"],nr=(rr=/[^.]+$/.exec(er&&er.keys&&er.keys.IE_PROTO||""))?"Symbol(src)_1."+rr:"";var or=Function.prototype.toString;function ar(t){if(null!=t){try{return or.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var ir=/^\[object .+?Constructor\]$/,ur=Function.prototype,cr=Object.prototype,sr=ur.toString,fr=cr.hasOwnProperty,lr=RegExp("^"+sr.call(fr).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pr(t){return!(!Bt(t)||function(t){return!!nr&&nr in t}(t))&&(Wt(t)?lr:ir).test(ar(t))}function hr(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pr(e)?e:void 0}var vr=hr(_,"Map"),gr=hr(Object,"create");var yr=Object.prototype.hasOwnProperty;var dr=Object.prototype.hasOwnProperty;function br(t){var r=-1,e=null==t?0:t.length;for(this.clear();++ru))return!1;var s=a.get(t);if(s&&a.get(r))return s==r;var f=-1,l=!0,p=2&e?new jr:void 0;for(a.set(t,r),a.set(r,t);++fr.type.filter((function(t){var r;return void 0===e||(!1!==(r=ct(t))?!st({arg:e},r):!it(t)(e))})).length)})).length}return!1},be=function(t,r){var e,n,o,a,i;switch(!0){case"object"===t:return o=(n=r).arg,a=n.param,i=[o],Array.isArray(a.keys)&&a.keys.length&&i.push(a.keys),!Reflect.apply(de,null,i);case"array"===t:return!ut(r.arg);case!1!==(e=ct(t)):return!st(r,e);default:return!it(t)(r.arg)}},_e=function(t,r){return void 0!==t?t:!0===r.optional&&void 0!==r.defaultvalue?r.defaultvalue:null},me=function(t,r,e){var n;void 0===e&&(e=!1);var o=function(t,r){if(!ut(r))throw new h("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===r.length)return[];if(!ut(t))throw new h("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==r.length:return t.map((function(t,e){return{arg:t,index:e,param:r[e]}}));case!0===r[0].variable:var e=r[0].type;return t.map((function(t,n){return{arg:t,index:n,param:r[n]||{type:e,name:"_"}}}));case t.lengthr.length:var n=r.length,o=["any"];return t.map((function(t,e){var a=e>=n||!!r[e].optional,i=r[e]||{type:o,name:"_"+e};return{arg:a?_e(t,i):t,index:e,param:i,optional:a}}));default:throw new h("Could not understand your arguments and parameter structure!",{args:t,params:r})}}(t,r),a=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var r=t.arg,e=t.param;return!!Z(r)&&!(e.type.length>e.type.filter((function(r){return be(r,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(r){return be(r,t)})).length)}));return e?((n={}).error=a,n.data=o.map((function(t){return t.arg})),n):a},we=function(){try{var t=hr(Object,"defineProperty");return t({},"",{}),t}catch(t){}}();function je(t,r,e){"__proto__"==r&&we?we(t,r,{configurable:!0,enumerable:!0,value:e,writable:!0}):t[r]=e}function Oe(t,r,e){(void 0===e||Qt(t[r],e))&&(void 0!==e||r in t)||je(t,r,e)}var Se="object"==typeof exports&&exports&&!exports.nodeType&&exports,ke=Se&&"object"==typeof module&&module&&!module.nodeType&&module,Ee=ke&&ke.exports===Se?_.Buffer:void 0,$e=Ee?Ee.allocUnsafe:void 0;function Te(t,r){var e,n,o=r?(e=t.buffer,n=new e.constructor(e.byteLength),new kr(n).set(new kr(e)),n):t.buffer;return new t.constructor(o,t.byteOffset,t.length)}var Ae=Object.create,Pe=function(){function t(){}return function(r){if(!Bt(r))return{};if(Ae)return Ae(r);t.prototype=r;var e=new t;return t.prototype=void 0,e}}();function Ne(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var ze=Object.prototype.hasOwnProperty;function Ce(t,r,e){var n=t[r];ze.call(t,r)&&Qt(n,e)&&(void 0!==e||r in t)||je(t,r,e)}var xe=Object.prototype.hasOwnProperty;function Re(t){if(!Bt(t))return function(t){var r=[];if(null!=t)for(var e in Object(t))r.push(e);return r}(t);var r=Dt(t),e=[];for(var n in t)("constructor"!=n||!r&&xe.call(t,n))&&e.push(n);return e}function qe(t){return Yt(t)?It(t,!0):Re(t)}function Me(t){return function(t,r,e,n){var o=!e;e||(e={});for(var a=-1,i=r.length;++a0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(Ue);function Ve(t,r){return He(function(t,r,e){return r=Ie(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,a=Ie(n.length-r,0),i=Array(a);++o1?r[n-1]:void 0,a=n>2?r[2]:void 0;for(o=Be.length>3&&"function"==typeof o?(n--,o):void 0,a&&function(t,r,e){if(!Bt(e))return!1;var n=typeof r;return!!("number"==n?Yt(e)&&Pt(r,e.length):"string"==n&&r in e)&&Qt(e[r],t)}(r[0],r[1],a)&&(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,ln(t))}),Reflect.apply(t,null,e))}};function yn(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))}}function dn(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}function bn(t,r,e,n){void 0===n&&(n=!1);var o=function(t,r){var e=Object.getOwnPropertyDescriptor(t,r);return void 0!==e&&e.value?e.value:e}(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t}function _n(t){return!!pn(t,"socket")&&t.socket}var mn=function(t){void 0===t&&(t=!1);var r=Date.now();return t?Math.floor(r/1e3):r};function wn(t,r,e){if(void 0===r&&(r=[]),void 0===e&&(e=!1),rt(t)&&j(r)){var n=function(t){var r;return(r={}).args=t,r}(r);return!0===e?n:function(t,r){var e;return(e={})[t]=r,e.TS=[mn()],e}(t,n)}throw new p("[createQuery] expect resolverName to be string and args to be array!",{resolverName:t,args:r})}var jn=new WeakMap,On=new WeakMap;var Sn=function(){this.__suspend__=null,this.queueStore=new Set},kn={$suspend:{configurable:!0},$queues:{configurable:!0}};kn.$suspend.set=function(t){var r=this;if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value!");var e=this.__suspend__;this.__suspend__=t,this.logger("($suspend)","Change from "+e+" --\x3e "+t),!0===e&&!1===t&&setTimeout((function(){r.release()}),1)},Sn.prototype.$queue=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return!0===this.__suspend__&&(this.logger("($queue)","added to $queue",t),this.queueStore.add(t)),this.__suspend__},kn.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},Sn.prototype.release=function(){var t=this,r=this.queueStore.size;if(this.logger("(release)","Release was called "+r),r>0){var e=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",e),e.forEach((function(r){t.logger(r),Reflect.apply(t.$trigger,t,r)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(Sn.prototype,kn);var En=function(t){function r(r){if("function"!=typeof r)throw new Error("Just die here the logger is not a function!");t.call(this,{logger:r})}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(r.prototype,e),r}(function(t){function r(r){void 0===r&&(r={}),t.call(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={$done:{configurable:!0}};return r.prototype.logger=function(){},r.prototype.$on=function(t,r,e){var n=this;void 0===e&&(e=null);this.validate(t,r);var o=this.takeFromStore(t);if(!1===o)return this.logger("($on)",t+" callback is not in lazy store"),this.addToNormalStore(t,"on",r,e);this.logger("($on)",t+" found in lazy store");var a=0;return o.forEach((function(o){var i=o[0],u=o[1],c=o[2];if(c&&"on"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);n.logger("($on)","call run on "+t),n.run(r,i,e||u),a+=n.addToNormalStore(t,"on",r,e||u)})),a},r.prototype.$once=function(t,r,e){void 0===e&&(e=null),this.validate(t,r);var n=this.takeFromStore(t);this.normalStore;if(!1===n)return this.logger("($once)",t+" not in the lazy store"),this.addToNormalStore(t,"once",r,e);this.logger("($once)",n);var o=Array.from(n)[0],a=o[0],i=o[1],u=o[2];if(u&&"once"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);this.logger("($once)","call run for "+t),this.run(r,a,e||i),this.$off(t)},r.prototype.$only=function(t,r,e){var n=this;void 0===e&&(e=null),this.validate(t,r);var o=!1,a=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger("($only)",t+" add to store"),o=this.addToNormalStore(t,"only",r,e)),!1!==a)&&(this.logger("($only)",t+" found data in lazy store to execute"),Array.from(a).forEach((function(o){var a=o[0],i=o[1],u=o[2];if(u&&"only"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);n.logger("($only)","call run for "+t),n.run(r,a,e||i)})));return o},r.prototype.$onlyOnce=function(t,r,e){void 0===e&&(e=null),this.validate(t,r);var n=!1,o=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger("($onlyOnce)",t+" add to store"),n=this.addToNormalStore(t,"onlyOnce",r,e)),!1!==o){this.logger("($onlyOnce)",o);var a=Array.from(o)[0],i=a[0],u=a[1],c=a[2];if(c&&"onlyOnce"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);this.logger("($onlyOnce)","call run for "+t),this.run(r,i,e||u),this.$off(t)}return n},r.prototype.$replace=function(t,r,e,n){if(void 0===e&&(e=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,r),Reflect.apply(o,this,[t,r,e])}throw new Error(n+" is not supported!")},r.prototype.$trigger=function(t,r,e,n){void 0===r&&(r=[]),void 0===e&&(e=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,a=this.normalStore;if(this.logger("($trigger)","normalStore",a),a.has(t)){var i=this.$queue(t,r,e,n);if(this.logger("($trigger)",t,"found; add to queue: ",i),!0===i)return this.logger("($trigger)",t,"not executed. Exit now."),!1;for(var u=Array.from(a.get(t)),c=u.length,s=!1,f=0;f0;)n[o]=arguments[o+2];if(t.has(r)?(this.logger("(addToStore)",r+" existed"),e=t.get(r)):(this.logger("(addToStore)","create new Set for "+r),e=new Set),n.length>2)if(Array.isArray(n[0])){var a=n[2];this.checkTypeInLazyStore(r,a)||e.add(n)}else this.checkContentExist(n,e)||(this.logger("(addToStore)","insert new",n),e.add(n));else e.add(n);return t.set(r,e),[t,e.size]},r.prototype.checkContentExist=function(t,r){return!!Array.from(r).filter((function(r){return r[0]===t[0]})).length},r.prototype.checkTypeInStore=function(t,r){this.validateEvt(t,r);var e=this.$get(t,!0);return!1===e||!e.filter((function(t){var e=t[3];return r!==e})).length},r.prototype.checkTypeInLazyStore=function(t,r){this.validateEvt(t,r);var e=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",e),!!e&&!!Array.from(e).filter((function(t){return t[2]!==r})).length},r.prototype.addToNormalStore=function(t,r,e,n){if(void 0===n&&(n=null),this.logger("(addToNormalStore)",t,r,"try to add to normal store"),this.checkTypeInStore(t,r)){this.logger("(addToNormalStore)",r+" can add to "+t+" normal store");var o=this.hashFnToKey(e),a=[this.normalStore,t,o,e,n,r],i=Reflect.apply(this.addToStore,this,a),u=i[0],c=i[1];return this.normalStore=u,c}return!1},r.prototype.addToLazyStore=function(t,r,e,n){void 0===r&&(r=[]),void 0===e&&(e=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(r),e];n&&o.push(n);var a=Reflect.apply(this.addToStore,this,o),i=a[0],u=a[1];return this.lazyStore=i,u},r.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},e.normalStore.set=function(t){jn.set(this,t)},e.normalStore.get=function(){return jn.get(this)},e.lazyStore.set=function(t){On.set(this,t)},e.lazyStore.get=function(){return On.get(this)},r.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,r){return(t=(t<<5)-t+r.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(r.prototype,e),r}(Sn)));function $n(t){var r,e,n=t.contract;return t.enableAuth?function(t,r){void 0===r&&(r=!1);var e=_n(t);if(!1===e){if(r)return t;throw new h("socket not found in contract!")}var n,o={},a=0;for(var i in e){var u=e[i],c=u.namespace;c&&(o[c]||(++a,o[c]={}),o[c][i]=u,n||u.public&&(n=c))}return{size:a,nspSet:o,publicNamespace:n}}(n):((e={}).nspSet=((r={}).jsonql=function(t){var r=_n(t);if(!1!==r)return r;throw new c("Missing property in contract!")}(n),r),e.publicNamespace="jsonql",e)}var Tn=function(t,r){ln(r).forEach((function(r){t.$off(hn(r,"emit"))}))};function An(t,r,e){pn(t,"error")?e(t.error):pn(t,"data")?r(t.data):e({message:"UKNNOWN RESULT!",error:t})}function Pn(t,r,e,n,o){void 0===o&&(o=[]);var a=hn(r,"emit"),i=n?"result":"onResult";return t.$trigger(a,[e,ln(o)]),new Promise((function(n,o){t.$on(hn(r,e,i),(function(t){An(t,n,o)}))}))}var Nn=function(t,r,e,n,o,a){return dn(t,"send",(function(t){var i=a?"error":"onError";cn(ln(t),o.params,!0).then((function(o){if(!o.error||!o.error.length)return Pn(r,e,n,a,t);r.$call(hn(e,n,i),[new p(n,o.error)])})).catch((function(t){r.$call(hn(e,n,i),[new p(n,t)])}))}),(function(){return function(){for(var t=[],i=arguments.length;i--;)t[i]=arguments[i];return cn(t,o.params,!0).then((function(t){return Pn(r,e,n,a,t)})).catch(g)}}))};function zn(t,r,e,n,o){return[bn(t,"on",(function(t,o){if(un(t)&&vn(o))switch(t){case"result":r.$on(hn(e,n,"onResult"),(function(t){An(t,o,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}));break;case"message":r.$only(hn(e,n,"onMessage"),(function(t){An(t,o,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}));break;case"ready":r.$only(hn(e,n,"onError"),o);break;default:r.$trigger(hn(e,n,"onError"),new h(n,"Unknown event name "+t+"!"))}})),r,e,n,o]}var Cn=function(t,r,e,n,o,a){return[bn(t,"myNamespace",e),r,e,n,o,a]},xn=function(t,r,e,n,o,a){return[dn(t,"onResult",(function(t){vn(t)&&r.$on(hn(e,n,"onResult"),(function(o){An(o,t,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}))})),r,e,n,o,a]},Rn=function(t,r,e,n,o,a){return[dn(t,"onMessage",(function(t){if(vn(t)){r.$only(hn(e,n,"onMessage"),(function(o){An(o,t,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}))}})),r,e,n,o,a]},qn=function(t,r,e,n,o,a){return[dn(t,"onError",(function(t){vn(t)&&r.$only(hn(e,n,"onError"),t)})),r,e,n,o,a]};function Mn(t,r,e,n,o,a){var i=[Cn];a?i.push(zn):i.push(xn,Rn,qn),i.push(Nn);var u=Reflect.apply(gn,null,i);return Reflect.apply(u,null,[n,o,t,r,e,a])}function Fn(t,r,e,n,o){return function(){for(var a=[],i=arguments.length;i--;)a[i]=arguments[i];return cn(a,n.params,!0).then((function(n){return Pn(t,r,e,o,n)})).catch(g)}}var Ln,Jn,In=function(t,r,e){return[bn(t,e.loginHandlerName,(function(t){if(t&&un(t))return r.$trigger("__login__",[t]);throw new p(e.loginHandlerName,"Unexpected token "+t)})),r,e]},Un=function(t,r,e){return bn(t,e.logoutHandlerName,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__logout__",t)}))};function Dn(t,r,e){var n={},o=r.nspSet,a=t.useCallbackStyle;for(var i in o){var u=o[i];for(var c in u){var s=u[c];n=bn(n,c,Mn(i,c,s,Fn(e,i,c,s,a),e,a))}}return n.devHelpers={getNsp:function(){return Object.keys(o)},getVer:function(){return t.version||"NOT SET"}},Promise.resolve(n)}function Hn(t,r,e){var n=r.nspSet,o=t.useCallbackStyle,a=t.enableAuth,i=[Dn];return o?i.push((function(t){return function(t,r,e,n){return bn(t,"on",(function(t,n){if(un(t)&&vn(n))switch(t){case"error":for(var o in e)r.$on(hn(o,"error"),n);break;case"login":r.$only("login",n);break;case"ready":r.$on("ready",n);break;default:r.$trigger("error",new h("on","Unknown event name "+t+"!"))}}))}(t,e,n)})):(i.push((function(t){return function(t,r,e){return dn(t,"onError",(function(t){if(vn(t))for(var n in e)r.$on(hn(n,"onError"),t)}))}(t,e,n)}),(function(t){return function(t,r,e){return dn(t,"onReady",(function(t){vn(t)&&r.$on("onReady",t)}))}(t,e)})),a&&i.push((function(r){return function(t,r,e){return e.enableAuth?dn(t,"onLogin",(function(t){vn(t)&&r.$only("onLogin",t)})):t}(r,e,t)}))),a&&i.push((function(r){return function(t,r,e){return e.enableAuth?gn(In,Un)(t,r,e):t}(r,e,t)})),Reflect.apply(yn,null,i)(t,r,e)}var Vn=["roundtip","handshake"],Bn={useCallbackStyle:sn(!1,["boolean"]),loginHandlerName:sn("login",["string"]),logoutHandlerName:sn("logout",["string"]),loginMethod:sn("handshake",["string"],(Ln={},Ln.enumv=Vn,Ln)),useJwt:sn(!0,["boolean","string"]),authStrKey:sn(null,["string"]),hostname:sn(!1,["string"]),namespace:sn("jsonql",["string"]),wsOptions:sn({},["object"]),contract:sn({},["object"],(Jn={},Jn.checker=function(t){return!!function(t){return dt(t)&&(pn(t,"query")||pn(t,"mutation")||pn(t,"socket"))}(t)&&t},Jn)),enableAuth:sn(!1,["boolean"]),token:sn(!1,["string"])},Wn={eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:""};function Yn(t){return Promise.resolve(t).then((function(t){var r;return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new p(t)}}()),t.wssPath=(r=[t.hostname,t.namespace].join("/"),"ws"===t.serverType?r.replace("http://","ws://"):r),t}))}function Kn(t,r,e){return function(t,r,e){var n=Object.assign(Wn,e),o=Object.assign(Bn,r);return fn(t,o,n)}(t,r,e).then(Yn)}var Gn=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];Reflect.apply(console.info,console,["[jsonql-ws-client-core]"].concat(t))},Qn=function(t){var r=t.log,e=t.eventEmitter;return r("CHECKED_KEY",t.__checked__),e?(r("eventEmitter is:",e.name),e):(r("Create a new Event Emitter"),new En(t.log))},Xn=function(t){var r=t.log;return r&&"function"==typeof r||(t.log=Gn),t.log("--- wsClientCore config opts ---",t),t};function Zn(t,r,e){return void 0===r&&(r={}),void 0===e&&(e={}),function(n){return void 0===n&&(n={}),Kn(n,r,e).then((function(r){return function(t,r){return Promise.resolve(r).then(Xn).then((function(t){return{opts:t,nspMap:$n(t),ee:Qn(t)}})).then((function(r){var e=r.opts,n=r.nspMap,o=r.ee;return t(e,n,o)})).then((function(t){return Hn(t.opts,t.nspMap,t.ee)})).catch((function(t){console.error("jsonql-ws-core-client init error",t)}))}(t,r)}))}}var to={version:"version: 1.1.0 module: cjs",serverType:"ws"},ro={},eo=function(t){var r=t.toLowerCase();return r.indexOf("http")>-1?r.indexOf("https")>-1?r.replace("https","wss"):r.replace("http","ws"):r};function no(t,r){return void 0===r&&(r=!1),!1===r?function(r){return new t(eo(r))}:function(r,e){var n=eo(r),o=e&&"string"==typeof e?n+"?token="+e:n;try{return new t(o)}catch(t){return console.error("WebSocket Connection Error",t),!1}}}function oo(t,r){var e=r.hostname,n=r.wssPath,o=r.wsOptions;return(0,r.nspClient)(t?[e,t].join("/"):n,o)}var ao=function(t,r,e){var n=e.useCallbackStyle,o=e.log,a=n?"error":"onError",i=n?"result":"onResult";r.$only(hn(t,"emit"),(function(e,n){o("[notLoginHandler] hijack the ws call",t,e,n);var u={message:"NOT LOGIN"};r.$call(hn(t,e,a),[u]),r.$call(hn(t,e,i),[{error:u}])}))};function io(t,r,e,n,o,a){var i=function(t){return t.length>1&&t[0]}(o),u=!1,c=t.log;o.forEach((function(o){if(u=i===o,a[o]){c("[call bindWsHandler]",u,o);var s=[o,a[o],e,u,t];if("socket.io"===t.serverType){var f=r.nspSet;s.push(f[o])}Reflect.apply(n,null,s)}else ao(o,e,t)})),e.$on("__logout__",(function(){c("LOGOUT_EVENT_NAME"),function(t,r,e,n){void 0===n&&(n={});var o=n.useCallbackStyle?"error":"onError";r.forEach((function(r){t.$call(hn(r,o),[{message:e,namespace:r}])}))}(e,o,"__logout__"),o.forEach((function(r){Tn(e,r),a[r]=!1,ao(r,e,t)}))}))}var uo=["__reply__","__event__","__data__"],co=function(t){var r,e=t.data;if(!1!==(r=function(t){var r=t.data;return!!r&&(uo.filter((function(t){return pn(r,t)})).length===uo.length&&r)}(un(e)?JSON.parse(e):e)))return{resolverName:r.__event__,data:r.__data__,type:r.__reply__};throw new h("payload can not be decoded",t)},so=function(t,r,e,n,o){var a=[r];e&&a.push(e),a.push(o);var i=Reflect.apply(hn,null,a),u=n.data||n;t.$trigger(i,[u])};function fo(t,r,e,n,o){var a=o.useCallbackStyle,i=o.log;i("wsMainHandler log test");var u=a?"ready":"onReady",c=a?"login":"onLogin",s=a?"message":"onMessage",f=a?"result":"onResult",l=a?"error":"onError";r.onopen=function(){i("ws.onopen listened"),e.$call(u,t),n&&(i("isPrivate and fire the "+c),e.$call(c,t)),e.$only(hn(t,"emit"),(function(t,e){i("calling server",t,e),r.send(function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(wn(t,r,e))}(t,e))}))},r.onmessage=function(r){try{var n=co(r),o=n.resolverName,a=n.type;switch(i("Hear from server",a,n),a){case"emit":var u=hn(t,o,s),c=e.$trigger(u,[n]);i("EMIT_REPLY_TYPE",u,c);break;case"acknowledge":var p=hn(t,o,f);e.$trigger(p,[n]);break;case"error":i("ERROR_TYPE"),so(e,t,o,n,l);break;default:i("Unhandled event!",n),so(e,t,o,n,l)}}catch(r){console.error("ws.onmessage error",r),so(e,t,!1,r,l)}},r.onclose=function(){i("ws.onclose callback")},e.$on("__logout__",(function(){try{i("terminate ws connection"),r.terminate()}catch(t){console.error("ws.terminate error",t)}}))}var lo=function(t,r,e){var n,o=r.nspSet,a=r.publicNamespace,i=!1,u=[],c={};if(t.enableAuth)i=!0,c=(u=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e}(o,a)).map((function(r,n){var o,a,i;return 0===n?e?(t.token=e,(o={})[r]=function(t,r){var e=r.hostname,n=r.wssPath,o=r.token,a=r.wsOptions,i=r.nspAuthClient,u=t?[e,t].join("/"):n;if(o&&"string"!=typeof o)throw new Error("Expect token to be string, but got "+o);return i(u,o,a)}(r,t),o):((a={})[r]=!1,a):((i={})[r]=oo(r,t),i)})).reduce((function(t,r){return Object.assign(t,r)}),{});else{var s=(n=o,Object.keys(n)[0]);u.push(s),c[s]=oo(!1,t)}return{nsps:c,namespaces:u,login:i}};var po,ho,vo,go=(ho=no(po=r),vo=no(po,!0),function(t,r,e){t.nspClient=ho,t.nspAuthClient=vo;var n=t.log;return n&&"function"==typeof n&&(n("@jsonql/ws ee",e.name),n("@jsonql/ws createClientResolver",t)),function(t,r,e){var n=[t,r,e,fo],o=t.token,a=t.log,i=lo(t,r,o),u=i.nsps,c=i.namespaces,s=i.login;return Reflect.apply(io,null,n.concat([c,u])),s&&e.$only("__login__",(function(o){a("createClient LOGIN_EVENT_NAME"),Tn(e,c);var i=lo(t,r,o);Reflect.apply(io,null,n.concat([i.namespaces,i.nsps]))})),{opts:t,nspMap:r,ee:e}}(t,r,e)});module.exports=function(t,r){return void 0===t&&(t={}),void 0===r&&(r={}),Zn(go,ro,Object.assign(to,r))(t)}; //# sourceMappingURL=main.js.map diff --git a/packages/@jsonql/ws/main.js.map b/packages/@jsonql/ws/main.js.map index 0bfeb3eb..aee0a927 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/jsonql-errors/src/500-error.js","node_modules/jsonql-errors/src/resolver-not-found-error.js","node_modules/jsonql-errors/src/enum-error.js","node_modules/jsonql-errors/src/type-error.js","node_modules/jsonql-errors/src/checker-error.js","node_modules/jsonql-errors/src/validation-error.js","node_modules/jsonql-errors/src/server-error.js","node_modules/jsonql-ws-client-core/src/options/constants.js","node_modules/rollup-plugin-node-globals/src/global.js","node_modules/lodash-es/_arrayMap.js","node_modules/lodash-es/isArray.js","node_modules/lodash-es/_objectToString.js","node_modules/lodash-es/isObjectLike.js","node_modules/lodash-es/_baseSlice.js","node_modules/lodash-es/_baseFindIndex.js","node_modules/lodash-es/_baseIsNaN.js","node_modules/lodash-es/_strictIndexOf.js","node_modules/lodash-es/_asciiToArray.js","node_modules/lodash-es/_hasUnicode.js","node_modules/lodash-es/_unicodeToArray.js","node_modules/jsonql-params-validator/src/number.js","node_modules/jsonql-params-validator/src/string.js","node_modules/jsonql-params-validator/src/boolean.js","node_modules/jsonql-params-validator/src/any.js","node_modules/jsonql-params-validator/src/constants.js","node_modules/jsonql-params-validator/src/combine.js","node_modules/jsonql-params-validator/src/array.js","node_modules/lodash-es/_overArg.js","node_modules/lodash-es/_arrayFilter.js","node_modules/lodash-es/_createBaseFor.js","node_modules/lodash-es/_baseTimes.js","node_modules/lodash-es/stubFalse.js","node_modules/lodash-es/_isIndex.js","node_modules/lodash-es/isLength.js","node_modules/lodash-es/_baseUnary.js","node_modules/lodash-es/_isPrototype.js","node_modules/lodash-es/isObject.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/_toSource.js","node_modules/lodash-es/_getValue.js","node_modules/lodash-es/_hashDelete.js","node_modules/lodash-es/_isKeyable.js","node_modules/lodash-es/_setCacheAdd.js","node_modules/lodash-es/_setCacheHas.js","node_modules/lodash-es/_arraySome.js","node_modules/lodash-es/_cacheHas.js","node_modules/lodash-es/_mapToArray.js","node_modules/lodash-es/_setToArray.js","node_modules/lodash-es/_arrayPush.js","node_modules/lodash-es/stubArray.js","node_modules/lodash-es/_matchesStrictComparable.js","node_modules/lodash-es/_baseHasIn.js","node_modules/lodash-es/identity.js","node_modules/lodash-es/_baseProperty.js","node_modules/jsonql-params-validator/src/object.js","node_modules/jsonql-params-validator/src/validator.js","node_modules/lodash-es/_copyArray.js","node_modules/lodash-es/_safeGet.js","node_modules/lodash-es/_nativeKeysIn.js","node_modules/lodash-es/_apply.js","node_modules/lodash-es/constant.js","node_modules/lodash-es/_shortOut.js","node_modules/lodash-es/negate.js","node_modules/lodash-es/_baseFindKey.js","node_modules/jsonql-params-validator/src/is-in-array.js","node_modules/jsonql-params-validator/src/options/run-validation.js","node_modules/jsonql-params-validator/src/options/check-options-async.js","node_modules/jsonql-params-validator/src/options/construct-config.js","node_modules/jsonql-params-validator/src/options/index.js","node_modules/jsonql-params-validator/index.js","node_modules/jsonql-utils/src/generic.js","node_modules/jsonql-utils/src/chain-promises.js","node_modules/jsonql-utils/src/contract.js","node_modules/jsonql-utils/src/timestamp.js","node_modules/jsonql-utils/src/params-api.js","node_modules/nb-event-service/src/hash-code.js","node_modules/nb-event-service/src/suspend.js","node_modules/nb-event-service/src/store-service.js","node_modules/nb-event-service/src/event-service.js","node_modules/nb-event-service/index.js","node_modules/jsonql-ws-client-core/src/utils/ee.js","node_modules/jsonql-ws-client-core/src/utils/process-contract.js","node_modules/jsonql-ws-client-core/src/utils/helpers.js","node_modules/jsonql-ws-client-core/src/core/respond-handler.js","node_modules/jsonql-ws-client-core/src/core/action-call.js","node_modules/jsonql-ws-client-core/src/core/setup-callback-api.js","node_modules/jsonql-ws-client-core/src/core/setup-resolver.js","node_modules/jsonql-ws-client-core/src/core/resolver-methods.js","node_modules/jsonql-ws-client-core/src/core/setup-auth-methods.js","node_modules/jsonql-ws-client-core/src/core/generator.js","node_modules/jsonql-ws-client-core/src/options/index.js","node_modules/jsonql-ws-client-core/src/api.js","src/options/index.js","src/core/create-ws-client.js","node_modules/jsonql-ws-client-core/src/share/create-nsp-client.js","node_modules/jsonql-ws-client-core/src/share/trigger-namespaces-on-error.js","node_modules/jsonql-ws-client-core/src/share/client-event-handler.js","src/core/extract-ws-payload.js","src/core/ws-main-handler.js","src/core/create-client.js","src/core/create-client-resolver.js","src/node-ws-client-resolver.js","src/node.js"],"sourcesContent":["/**\n * This is a custom error to throw when server throw a 500\n * This help us to capture the right error, due to the call happens in sequence\n * @param {string} message to tell what happen\n * @param {mixed} extra things we want to add, 500?\n */\nexport default class Jsonql500Error extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = Jsonql500Error.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, Jsonql500Error)\n }\n }\n\n static get statusCode() {\n return 500;\n }\n\n static get name() {\n return 'Jsonql500Error';\n }\n\n}\n","/**\n * This is a custom error to throw when could not find the resolver\n * This help us to capture the right error, due to the call happens in sequence\n * @param {string} message to tell what happen\n * @param {mixed} extra things we want to add, 500?\n */\nexport default class JsonqlResolverNotFoundError extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlResolverNotFoundError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlResolverNotFoundError);\n }\n }\n\n static get statusCode() {\n return 404;\n }\n\n static get name() {\n return 'JsonqlResolverNotFoundError';\n }\n}\n","// this get throw from within the checkOptions when run through the enum failed\nexport default class JsonqlEnumError extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlEnumError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlEnumError);\n }\n }\n\n static get name() {\n return 'JsonqlEnumError';\n }\n}\n","// this will throw from inside the checkOptions\nexport default class JsonqlTypeError extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlTypeError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlTypeError);\n }\n }\n\n static get name() {\n return 'JsonqlTypeError';\n }\n}\n","// allow supply a custom checker function\n// if that failed then we throw this error\nexport default class JsonqlCheckerError extends Error {\n constructor(...args) {\n super(...args)\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlCheckerError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlCheckerError)\n }\n }\n\n static get name() {\n return 'JsonqlCheckerError';\n }\n}\n","// custom validation error class\n// when validaton failed\nexport default class JsonqlValidationError extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlValidationError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlValidationError)\n }\n }\n\n static get name() {\n return 'JsonqlValidationError';\n }\n}\n","// this is from an example from Koa team to use for internal middleware ctx.throw\n// but after the test the res.body part is unable to extract the required data\n// I keep this one here for future reference\n\nexport default class JsonqlServerError extends Error {\n\n constructor(statusCode, message) {\n super(message)\n this.statusCode = statusCode;\n this.className = JsonqlServerError.name;\n }\n\n static get name() {\n return 'JsonqlServerError';\n }\n}\n","// constants\n\nimport {\n EMIT_REPLY_TYPE,\n JS_WS_SOCKET_IO_NAME,\n JS_WS_NAME,\n ON_MESSAGE_PROP_NAME,\n ON_RESULT_PROP_NAME\n} from 'jsonql-constants'\n\nconst SOCKET_IO = JS_WS_SOCKET_IO_NAME;\nconst WS = JS_WS_NAME;\n\nconst AVAILABLE_SERVERS = [SOCKET_IO, WS]\n\nconst SOCKET_NOT_DEFINE_ERR = 'socket is not define in the contract file!';\n\nconst SERVER_NOT_SUPPORT_ERR = 'is not supported server name!';\n\nconst MISSING_PROP_ERR = 'Missing property in contract!';\n\nconst UNKNOWN_CLIENT_ERR = 'Unknown client type!';\n\nconst EMIT_EVT = EMIT_REPLY_TYPE;\n\nconst NAMESPACE_KEY = 'namespaceMap';\n\nconst UNKNOWN_RESULT = 'UKNNOWN RESULT!';\n\nconst NOT_ALLOW_OP = 'This operation is not allow!';\n\nconst MY_NAMESPACE = 'myNamespace'\n\nconst CB_FN_NAME = 'on'\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_PROP_NAME,\n ON_RESULT_PROP_NAME,\n NAMESPACE_KEY,\n UNKNOWN_RESULT,\n NOT_ALLOW_OP,\n MY_NAMESPACE,\n CB_FN_NAME\n}\n","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\nexport const ARGS_NOT_ARRAY_ERR = `args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)`;\nexport const PARAMS_NOT_ARRAY_ERR = `params is not an array! Did something gone wrong when you generate the contract.json?`;\nexport const EXCEPTION_CASE_ERR = 'Could not understand your arguments and parameter structure!';\nexport const UNUSUAL_CASE_ERR = 'This is an unusual situation where the arguments are more than the params, but not mark as spread';\n\n// re-export\nimport * as JSONQL_CONSTANTS from 'jsonql-constants';\n// @TODO the jsdoc return array. and we should also allow array syntax\nexport const DEFAULT_TYPE = JSONQL_CONSTANTS.DEFAULT_TYPE;\nexport const ARRAY_TYPE_LFT = JSONQL_CONSTANTS.ARRAY_TYPE_LFT;\nexport const ARRAY_TYPE_RGT = JSONQL_CONSTANTS.ARRAY_TYPE_RGT;\n\nexport const TYPE_KEY = JSONQL_CONSTANTS.TYPE_KEY;\nexport const OPTIONAL_KEY = JSONQL_CONSTANTS.OPTIONAL_KEY;\nexport const ENUM_KEY = JSONQL_CONSTANTS.ENUM_KEY;\nexport const ARGS_KEY = JSONQL_CONSTANTS.ARGS_KEY;\nexport const CHECKER_KEY = JSONQL_CONSTANTS.CHECKER_KEY;\nexport const ALIAS_KEY = JSONQL_CONSTANTS.ALIAS_KEY;\n\nexport const ARRAY_TYPE = JSONQL_CONSTANTS.ARRAY_TYPE;\nexport const OBJECT_TYPE = JSONQL_CONSTANTS.OBJECT_TYPE;\nexport const STRING_TYPE = JSONQL_CONSTANTS.STRING_TYPE;\nexport const BOOLEAN_TYPE = JSONQL_CONSTANTS.BOOLEAN_TYPE;\nexport const NUMBER_TYPE = JSONQL_CONSTANTS.NUMBER_TYPE;\nexport const KEY_WORD = JSONQL_CONSTANTS.KEY_WORD;\nexport const OR_SEPERATOR = JSONQL_CONSTANTS.OR_SEPERATOR;\n\n// not actually in use\n// export const NUMBER_TYPES = JSONQL_CONSTANTS.NUMBER_TYPES;\n","// primitive types\nimport checkIsNumber from './number'\nimport checkIsString from './string'\nimport checkIsBoolean from './boolean'\nimport checkIsAny from './any'\nimport { NUMBER_TYPE, STRING_TYPE, BOOLEAN_TYPE } from './constants'\n\n/**\n * this is a wrapper method to call different one based on their type\n * @param {string} type to check\n * @return {function} a function to handle the type\n */\nconst combineFn = function(type) {\n switch (type) {\n case NUMBER_TYPE:\n return checkIsNumber;\n case STRING_TYPE:\n return checkIsString;\n case BOOLEAN_TYPE:\n return checkIsBoolean;\n default:\n return checkIsAny;\n }\n}\n\nexport default combineFn\n","// validate array type\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","/**\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 * 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 * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\nexport default baseTimes;\n","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n return false;\n}\n\nexport default stubFalse;\n","/** 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","/** 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 * 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","/** 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 the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nexport default isObject;\n","/**\n * 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","/** 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","/** 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 * 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 * 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 * 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","// validate object type\n\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport filter from 'lodash-es/filter'\n\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 checkIsObject,\n combineFn,\n notEmpty\n} from './index'\nimport {\n DEFAULT_TYPE,\n ARRAY_TYPE,\n OBJECT_TYPE,\n ARGS_NOT_ARRAY_ERR,\n PARAMS_NOT_ARRAY_ERR,\n EXCEPTION_CASE_ERR,\n UNUSUAL_CASE_ERR\n} from './constants'\nimport { DATA_KEY, ERROR_KEY } from 'jsonql-constants'\nimport { JsonqlError } from 'jsonql-errors'\n// 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 JsonqlError(PARAMS_NOT_ARRAY_ERR)\n }\n if (params.length === 0) {\n return [];\n }\n if (!checkIsArray(args)) {\n throw new JsonqlError(ARGS_NOT_ARRAY_ERR)\n }\n // debugFn(args, params);\n // fall through switch\n switch(true) {\n case args.length == params.length: // standard\n return args.map((arg, i) => (\n {\n arg,\n index: i,\n param: params[i]\n }\n ))\n case params[0].variable === true: // using spread syntax\n const type = params[0].type;\n return args.map((arg, i) => (\n {\n arg,\n index: i, // keep the index for reference\n param: params[i] || { type, name: '_' }\n }\n ))\n // with optional defaultValue parameters\n case args.length < params.length:\n return params.map((param, i) => (\n {\n param,\n index: i,\n arg: getOptionalValue(args[i], param),\n optional: param.optional || false\n }\n ))\n // this one pass more than it should have anything after the args.length will be cast as any type\n case args.length > params.length:\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 * 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","/**\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 * 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 * 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","/** 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'\nimport 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'\n// PIA syntax\nexport const isObject = checkIsObject;\nexport const isAny = checkIsAny;\nexport const isString = checkIsString;\nexport const isBoolean = checkIsBoolean;\nexport const isNumber = checkIsNumber;\nexport const isArray = checkIsArray;\nexport const isNotEmpty = notEmpty;\n\nimport * as validator from './src/validator'\n\nexport const normalizeArgs = validator.normalizeArgs;\nexport const validateSync = validator.validateSync;\nexport const validateAsync = validator.validateAsync;\n\n// configuration checking\n\nimport * as jsonqlOptions from './src/options'\n\nexport const JSONQL_PARAMS_VALIDATOR_INFO = jsonqlOptions.JSONQL_PARAMS_VALIDATOR_INFO;\n\nexport const createConfig = jsonqlOptions.createConfig;\nexport const constructConfig = jsonqlOptions.constructConfigFn;\n// construct the final output 1.5.2\nexport const checkConfigAsync = jsonqlOptions.getCheckConfigAsync(validator.validateSync)\nexport const checkConfig = jsonqlOptions.getCheckConfig(validator.validateSync)\n\n// export the two extra functions\nimport isInArray from './src/is-in-array'\nimport isObjectHasKeyFn from './src/options/is-key-in-object'\n\nexport const inArray = isInArray;\nexport const isObjectHasKey = isObjectHasKeyFn;\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 * @return {*} json object on success\n */\nconst parse = function(n) {\n try {\n return JSON.parse(n)\n } catch(e) {\n return n;\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 console.info('obj', obj)\n console.error(e)\n throw new Error(e)\n */\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 parse(n)\n }\n return JSON.parse(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","// 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","// 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')) {\n return contract.socket;\n }\n return false;\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 * @param {boolean} [fallback=false] this is a fall back option for old code\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, fallback = false) {\n let socket = extractSocketPart(contract)\n if (socket === false) {\n if (fallback) {\n return contract; // just return the whole contract\n }\n throw new JsonqlError(`socket not found in contract!`)\n }\n let nspSet = {};\n let size = 0;\n let publicNamespace;\n for (let resolverName in socket) {\n let params = socket[resolverName];\n let { namespace } = params;\n if (namespace) {\n if (!nspSet[namespace]) {\n ++size;\n nspSet[namespace] = {};\n }\n nspSet[namespace][resolverName] = params;\n if (!publicNamespace) {\n if (params.public) {\n publicNamespace = namespace;\n }\n }\n }\n }\n return { size, nspSet, publicNamespace }\n}\n\n/**\n * @NOTE ported from jsonql-ws-client\n * Got to make sure the connection order otherwise\n * it will hang\n * @param {object} nspSet contract\n * @param {string} publicNamespace like the name said\n * @return {array} namespaces in order\n */\nexport function getNamespaceInOrder(nspSet, publicNamespace) {\n let names = []; // need to make sure the order!\n for (let namespace in nspSet) {\n if (namespace === publicNamespace) {\n names[1] = namespace;\n } else {\n names[0] = namespace;\n }\n }\n return names;\n}\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'\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\n\nimport isArray from 'lodash-es/isArray'\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport isString from 'lodash-es/isString'\n\nimport { timestamp } from './timestamp'\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) ? JSON.parse(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 * Get name from the payload (ported back from jsonql-koa)\n * @param {*} payload to extract from\n * @return {string} name\n */\nexport function getNameFromPayload(payload) {\n return Object.keys(payload)[0]\n}\n\n/**\n * 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]: payload[TIMESTAMP_PARAM_NAME]\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 = getNameFromPayload(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]: payload[TIMESTAMP_PARAM_NAME]\n }\n }\n }\n return false;\n}\n\n/**\n * @param {object} payload\n * @return {object} resolverName, payload, conditon\n */\nexport function getMutationFromPayload(payload) {\n const result = processPayload(payload, getMutationFromArgs)\n\n if (result !== false) {\n return result;\n }\n throw new JsonqlValidationError('[getMutationArgs] Payload is malformed!', payload)\n}\n","/**\n * generate a 32bit hash based on the function.toString()\n * _from http://stackoverflow.com/questions/7616461/generate-a-hash-_from-string-in-javascript-jquery\n * @param {string} s the converted to string function\n * @return {string} the hashed function string\n */\nexport function hashCode(s) {\n\treturn s.split(\"\").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0)\n}\n// wrapper to make sure it string \nexport function hashCode2Str(s) {\n return hashCode(s) + ''\n}\n","// making all the functionality on it's own\n// import { WatchClass } from './watch'\n\nexport default class SuspendClass {\n\n constructor() {\n // suspend, release and queue\n this.__suspend__ = null;\n this.queueStore = new Set()\n /*\n this.watch('suspend', function(value, prop, oldValue) {\n this.logger(`${prop} set from ${oldValue} to ${value}`)\n // it means it set the suspend = true then release it\n if (oldValue === true && value === false) {\n // we want this happen after the return happens\n setTimeout(() => {\n this.release()\n }, 1)\n }\n return value; // we need to return the value to store it\n })\n */\n }\n\n /**\n * setter to set the suspend and check if it's boolean value\n * @param {boolean} value to trigger\n */\n set $suspend(value) {\n if (typeof value === 'boolean') {\n const lastValue = this.__suspend__;\n this.__suspend__ = value;\n this.logger('($suspend)', `Change from ${lastValue} --> ${value}`)\n if (lastValue === true && value === false) {\n setTimeout(() => {\n this.release()\n }, 1)\n }\n } else {\n throw new Error(`$suspend only accept Boolean value!`)\n }\n }\n\n /**\n * queuing call up when it's in suspend mode\n * @param {any} value\n * @return {Boolean} true when added or false when it's not\n */\n $queue(...args) {\n if (this.__suspend__ === true) {\n this.logger('($queue)', 'added to $queue', args)\n // there shouldn't be any duplicate ...\n this.queueStore.add(args)\n }\n return this.__suspend__;\n }\n\n /**\n * a getter to get all the store queue\n * @return {array} Set turn into Array before return\n */\n get $queues() {\n let size = this.queueStore.size;\n this.logger('($queues)', `size: ${size}`)\n if (size > 0) {\n return Array.from(this.queueStore)\n }\n return []\n }\n\n /**\n * Release the queue\n * @return {int} size if any\n */\n release() {\n let size = this.queueStore.size\n this.logger('(release)', `Release was called ${size}`)\n if (size > 0) {\n const queue = Array.from(this.queueStore)\n this.queueStore.clear()\n this.logger('queue', queue)\n queue.forEach(args => {\n this.logger(args)\n Reflect.apply(this.$trigger, this, args)\n })\n this.logger(`Release size ${this.queueStore.size}`)\n }\n }\n}\n","// break up the main file because its getting way too long\nimport {\n NB_EVENT_SERVICE_PRIVATE_STORE,\n NB_EVENT_SERVICE_PRIVATE_LAZY\n} from './store'\nimport { hashCode2Str } from './hash-code'\nimport SuspendClass from './suspend'\n\nexport default class NbEventServiceBase extends SuspendClass {\n\n constructor(config = {}) {\n super()\n if (config.logger && typeof config.logger === 'function') {\n this.logger = config.logger;\n }\n this.keep = config.keep;\n // for the $done setter\n this.result = config.keep ? [] : null;\n // we need to init the store first otherwise it could be a lot of checking later\n this.normalStore = new Map()\n this.lazyStore = new Map()\n }\n\n // for id if the instance is this class\n get is() {\n return 'nb-event-service'\n }\n\n /**\n * validate the event name(s)\n * @param {string[]} evt event name\n * @return {boolean} true when OK\n */\n validateEvt(...evt) {\n evt.forEach(e => {\n if (typeof e !== 'string') {\n this.logger('(validateEvt)', e)\n throw new Error(`event name must be string type!`)\n }\n })\n return true;\n }\n\n /**\n * Simple quick check on the two main parameters\n * @param {string} evt event name\n * @param {function} callback function to call\n * @return {boolean} true when OK\n */\n validate(evt, callback) {\n if (this.validateEvt(evt)) {\n if (typeof callback === 'function') {\n return true;\n }\n }\n throw new Error(`callback required to be function type!`)\n }\n\n /**\n * Check if this type is correct or not added in V1.5.0\n * @param {string} type for checking\n * @return {boolean} true on OK\n */\n validateType(type) {\n const types = ['on', 'only', 'once', 'onlyOnce']\n return !!types.filter(t => type === t).length;\n }\n\n /**\n * Run the callback\n * @param {function} callback function to execute\n * @param {array} payload for callback\n * @param {object} ctx context or null\n * @return {void} the result store in $done\n */\n run(callback, payload, ctx) {\n this.logger('(run)', callback, payload, ctx)\n this.$done = Reflect.apply(callback, ctx, this.toArray(payload))\n }\n\n /**\n * Take the content out and remove it from store id by the name\n * @param {string} evt event name\n * @param {string} [storeName = lazyStore] name of store\n * @return {object|boolean} content or false on not found\n */\n takeFromStore(evt, storeName = 'lazyStore') {\n let store = this[storeName] // it could be empty at this point\n if (store) {\n this.logger('(takeFromStore)', storeName, store)\n if (store.has(evt)) {\n let content = store.get(evt)\n this.logger('(takeFromStore)', `has ${evt}`, content)\n store.delete(evt)\n return content;\n }\n return false;\n }\n throw new Error(`${storeName} is not supported!`)\n }\n\n /**\n * The add to store step is similar so make it generic for resuse\n * @param {object} store which store to use\n * @param {string} evt event name\n * @param {spread} args because the lazy store and normal store store different things\n * @return {array} store and the size of the store\n */\n addToStore(store, evt, ...args) {\n let fnSet;\n if (store.has(evt)) {\n this.logger('(addToStore)', `${evt} existed`)\n fnSet = store.get(evt)\n } else {\n this.logger('(addToStore)', `create new Set for ${evt}`)\n // this is new\n fnSet = new Set()\n }\n // lazy only store 2 items - this is not the case in V1.6.0 anymore\n // we need to check the first parameter is string or not\n if (args.length > 2) {\n if (Array.isArray(args[0])) { // lazy store\n // check if this type of this event already register in the lazy store\n let [,,t] = args;\n if (!this.checkTypeInLazyStore(evt, t)) {\n fnSet.add(args)\n }\n } else {\n if (!this.checkContentExist(args, fnSet)) {\n this.logger('(addToStore)', `insert new`, args)\n fnSet.add(args)\n }\n }\n } else { // add straight to lazy store\n fnSet.add(args)\n }\n store.set(evt, fnSet)\n return [store, fnSet.size]\n }\n\n /**\n * @param {array} args for compare\n * @param {object} fnSet A Set to search from\n * @return {boolean} true on exist\n */\n checkContentExist(args, fnSet) {\n let list = Array.from(fnSet)\n return !!list.filter(l => {\n let [hash,] = l;\n if (hash === args[0]) {\n return true;\n }\n return false;\n }).length;\n }\n\n /**\n * get the existing type to make sure no mix type add to the same store\n * @param {string} evtName event name\n * @param {string} type the type to check\n * @return {boolean} true you can add, false then you can't add this type\n */\n checkTypeInStore(evtName, type) {\n this.validateEvt(evtName, type)\n let all = this.$get(evtName, true)\n if (all === false) {\n // pristine it means you can add\n return true;\n }\n // it should only have ONE type in ONE event store\n return !all.filter(list => {\n let [ ,,,t ] = list;\n return type !== t;\n }).length;\n }\n\n /**\n * This is checking just the lazy store because the structure is different\n * therefore we need to use a new method to check it\n */\n checkTypeInLazyStore(evtName, type) {\n this.validateEvt(evtName, type)\n let store = this.lazyStore.get(evtName)\n this.logger('(checkTypeInLazyStore)', store)\n if (store) {\n return !!Array\n .from(store)\n .filter(l => {\n let [,,t] = l;\n return t !== type;\n }).length\n }\n return false;\n }\n\n /**\n * wrapper to re-use the addToStore,\n * V1.3.0 add extra check to see if this type can add to this evt\n * @param {string} evt event name\n * @param {string} type on or once\n * @param {function} callback function\n * @param {object} context the context the function execute in or null\n * @return {number} size of the store\n */\n addToNormalStore(evt, type, callback, context = null) {\n this.logger('(addToNormalStore)', evt, type, 'try to add to normal store')\n // @TODO we need to check the existing store for the type first!\n if (this.checkTypeInStore(evt, type)) {\n this.logger('(addToNormalStore)', `${type} can add to ${evt} normal store`)\n let key = this.hashFnToKey(callback)\n let args = [this.normalStore, evt, key, callback, context, type]\n let [_store, size] = Reflect.apply(this.addToStore, this, args)\n this.normalStore = _store;\n return size;\n }\n return false;\n }\n\n /**\n * Add to lazy store this get calls when the callback is not register yet\n * so we only get a payload object or even nothing\n * @param {string} evt event name\n * @param {array} payload of arguments or empty if there is none\n * @param {object} [context=null] the context the callback execute in\n * @param {string} [type=false] register a type so no other type can add to this evt\n * @return {number} size of the store\n */\n addToLazyStore(evt, payload = [], context = null, type = false) {\n // this is add in V1.6.0\n // when there is type then we will need to check if this already added in lazy store\n // and no other type can add to this lazy store\n let args = [this.lazyStore, evt, this.toArray(payload), context]\n if (type) {\n args.push(type)\n }\n let [_store, size] = Reflect.apply(this.addToStore, this, args)\n this.lazyStore = _store;\n return size;\n }\n\n /**\n * make sure we store the argument correctly\n * @param {*} arg could be array\n * @return {array} make sured\n */\n toArray(arg) {\n return Array.isArray(arg) ? arg : [arg];\n }\n\n /**\n * setter to store the Set in private\n * @param {object} obj a Set\n */\n set normalStore(obj) {\n NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj)\n }\n\n /**\n * @return {object} Set object\n */\n get normalStore() {\n return NB_EVENT_SERVICE_PRIVATE_STORE.get(this)\n }\n\n /**\n * setter to store the Set in lazy store\n * @param {object} obj a Set\n */\n set lazyStore(obj) {\n NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj)\n }\n\n /**\n * @return {object} the lazy store Set\n */\n get lazyStore() {\n return NB_EVENT_SERVICE_PRIVATE_LAZY.get(this)\n }\n\n /**\n * generate a hashKey to identify the function call\n * The build-in store some how could store the same values!\n * @param {function} fn the converted to string function\n * @return {string} hashKey\n */\n hashFnToKey(fn) {\n return hashCode2Str(fn.toString())\n }\n}\n","// The top level\nimport NbStoreService from './store-service'\n// export\nexport default class EventService extends NbStoreService {\n /**\n * class constructor\n */\n constructor(config = {}) {\n super(config)\n }\n\n /**\n * logger function for overwrite\n */\n logger() {}\n\n //////////////////////////\n // PUBLIC METHODS //\n //////////////////////////\n\n /**\n * Register your evt handler, note we don't check the type here,\n * we expect you to be sensible and know what you are doing.\n * @param {string} evt name of event\n * @param {function} callback bind method --> if it's array or not\n * @param {object} [context=null] to execute this call in\n * @return {number} the size of the store\n */\n $on(evt , callback , context = null) {\n const type = 'on';\n this.validate(evt, callback)\n // first need to check if this evt is in lazy store\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register first then call later\n if (lazyStoreContent === false) {\n this.logger('($on)', `${evt} callback is not in lazy store`)\n // @TODO we need to check if there was other listener to this\n // event and are they the same type then we could solve that\n // register the different type to the same event name\n\n return this.addToNormalStore(evt, type, callback, context)\n }\n this.logger('($on)', `${evt} found in lazy store`)\n // this is when they call $trigger before register this callback\n let size = 0;\n lazyStoreContent.forEach(content => {\n let [ payload, ctx, t ] = content;\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.logger(`($on)`, `call run on ${evt}`)\n this.run(callback, payload, context || ctx)\n size += this.addToNormalStore(evt, type, callback, context || ctx)\n })\n return size;\n }\n\n /**\n * once only registered it once, there is no overwrite option here\n * @NOTE change in v1.3.0 $once can add multiple listeners\n * but once the event fired, it will remove this event (see $only)\n * @param {string} evt name\n * @param {function} callback to execute\n * @param {object} [context=null] the handler execute in\n * @return {boolean} result\n */\n $once(evt , callback , context = null) {\n this.validate(evt, callback)\n const type = 'once';\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register before call $trigger\n let nStore = this.normalStore;\n if (lazyStoreContent === false) {\n this.logger('($once)', `${evt} not in the lazy store`)\n // v1.3.0 $once now allow to add multiple listeners\n return this.addToNormalStore(evt, type, callback, context)\n } else {\n // now this is the tricky bit\n // there is a potential bug here that cause by the developer\n // if they call $trigger first, the lazy won't know it's a once call\n // so if in the middle they register any call with the same evt name\n // then this $once call will be fucked - add this to the documentation\n this.logger('($once)', lazyStoreContent)\n const list = Array.from(lazyStoreContent)\n // should never have more than 1\n const [ payload, ctx, t ] = list[0]\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.logger('($once)', `call run for ${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 store`)\n added = this.addToNormalStore(evt, type, callback, context)\n }\n if (lazyStoreContent !== false) {\n // there are data store in lazy store\n this.logger('($only)', `${evt} found data in lazy store to execute`)\n const list = Array.from(lazyStoreContent)\n // $only allow to trigger this multiple time on the single handler\n list.forEach( l => {\n const [ payload, ctx, t ] = l;\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.logger(`($only)`, `call run for ${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 store`)\n added = this.addToNormalStore(evt, type, callback, context)\n }\n if (lazyStoreContent !== false) {\n // there are data store in lazy store\n this.logger('($onlyOnce)', lazyStoreContent)\n const list = Array.from(lazyStoreContent)\n // should never have more than 1\n const [ payload, ctx, t ] = list[0]\n if (t && t !== 'onlyOnce') {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.logger(`($onlyOnce)`, `call run for ${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 // @1.8.0 to add the suspend queue\n let added = this.$queue(evt, payload, context, type)\n this.logger('($trigger)', evt, 'found; add to queue: ', added)\n if (added === true) {\n this.logger('($trigger)', evt, 'not 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 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 this.validateEvt(evt)\n let stores = [ this.lazyStore, this.normalStore ]\n let found = false;\n stores.forEach(store => {\n if (store.has(evt)) {\n found = true;\n this.logger('($off)', evt)\n store.delete(evt)\n }\n })\n return found;\n }\n\n /**\n * return all the listener from the event\n * @param {string} evtName event name\n * @param {boolean} [full=false] if true then return the entire content\n * @return {array|boolean} listerner(s) or false when not found\n */\n $get(evt, full = false) {\n this.validateEvt(evt)\n let store = this.normalStore;\n if (store.has(evt)) {\n return Array\n .from(store.get(evt))\n .map( l => {\n if (full) {\n return l;\n }\n let [key, callback, ] = l;\n return callback;\n })\n }\n return false;\n }\n\n /**\n * store the return result from the run\n * @param {*} value whatever return from callback\n */\n set $done(value) {\n this.logger('($done)', 'value: ', value)\n if (this.keep) {\n this.result.push(value)\n } else {\n this.result = value;\n }\n }\n\n /**\n * @TODO is there any real use with the keep prop?\n * getter for $done\n * @return {*} whatever last store result\n */\n get $done() {\n if (this.keep) {\n this.logger('(get $done)', this.result)\n return this.result[this.result.length - 1]\n }\n return this.result;\n }\n\n\n}\n","// default\nimport NBEventService from './src/event-service'\n\nexport default NBEventService\n","// this will generate a event emitter and will be use everywhere\nimport NBEventService from 'nb-event-service'\n// create a clone version so we know which one we actually is using\nexport default class JsonqlWsEvt extends NBEventService {\n\n constructor(logger) {\n if (typeof logger !== 'function') {\n throw new Error(`Just die here the logger is not a function!`)\n }\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","// mapping the resolver to their respective nsp\nimport { JSONQL_PATH, NSP_SET, PUBLIC_NAMESPACE } from 'jsonql-constants'\nimport { groupByNamespace, extractSocketPart } from 'jsonql-utils/module'\nimport { JsonqlResolverNotFoundError } from 'jsonql-errors'\n\nimport { MISSING_PROP_ERR } from '../options/constants'\n\n/**\n * Just make sure the object contain what we are looking for\n * @param {object} opts configuration from checkOptions\n * @return {object} the target content\n */\nconst getResolverList = contract => {\n const result = extractSocketPart(contract)\n if (result !== false) {\n return result\n }\n throw new JsonqlResolverNotFoundError(MISSING_PROP_ERR)\n}\n\n/**\n * process the contract first\n * @param {object} opts configuration\n * @return {object} sorted list\n */\nexport default function processContract(opts) {\n const { contract, enableAuth } = opts\n if (enableAuth) {\n return groupByNamespace(contract)\n }\n return {\n [NSP_SET]: { [JSONQL_PATH]: getResolverList(contract) },\n [PUBLIC_NAMESPACE]: JSONQL_PATH\n }\n}\n","// group all the small functions here\nimport { JS_WS_SOCKET_IO_NAME, JS_WS_NAME, EMIT_REPLY_TYPE } from 'jsonql-constants'\nimport { toArray, createEvt } from 'jsonql-utils/src/generic'\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\n// we shouldn't do this anymore\nexport const fixWss = (url, serverType) => {\n // ws only allow ws:// path\n if (serverType === JS_WS_NAME) {\n return url.replace('http://', 'ws://')\n }\n return url\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 * @param {object} nsps namespace as key\n * @param {string} type of server\n */\nexport const disconnect = (nsps, type = JS_WS_SOCKET_IO_NAME) => {\n try {\n // @TODO need to figure out a better way here?\n const method = type === JS_WS_SOCKET_IO_NAME ? 'disconnect' : 'terminate';\n for (let namespace in nsps) {\n let nsp = nsps[namespace]\n if (nsp && nsp[method]) {\n Reflect.apply(nsp[method], null, [])\n }\n }\n } catch(e) {\n // socket.io throw a this.destroy of undefined?\n console.error('Disconnect call failed', e)\n }\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_PROP_NAME, RESULT_PROP_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 {boolean} useCallbackStyle use on or not\n * @param {array} args arguments\n * @return {void} nothing\n */\nexport function actionCall(ee, namespace, resolverName, useCallbackStyle, args = []) {\n const eventName = createEvt(namespace, EMIT_REPLY_TYPE)\n const RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME\n // debugFn(`actionCall: ${eventName} --> ${resolverName}`, args)\n ee.$trigger(eventName, [resolverName, toArray(args)])\n // once we trigger there is nothing return from the resolve\n // @TODO if we need the next then call to have the result back\n // then we need to listen to the event callback here as well\n return new Promise((resolver, rejecter) => {\n ee.$on(\n createEvt(namespace, resolverName, RESULT_SUBFIX),\n function actionCallResultHandler(result) {\n // debugFn(`got the first result`, result)\n respondHandler(result, resolver, rejecter)\n }\n )\n })\n}\n","// @TODO using the obj.on syntax to do the same thing\n/*\nThe new callback style `useCallbackStyle` set to true then use this one\nclient.resolverName.on(EVENT_NAME, cb)\n*/\nimport { JsonqlValidationError, JsonqlError, finalCatch } from 'jsonql-errors'\nimport {\n ERROR_TYPE,\n DATA_KEY,\n ERROR_KEY,\n ERROR_PROP_NAME,\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME,\n READY_PROP_NAME,\n ON_ERROR_PROP_NAME,\n ON_RESULT_PROP_NAME,\n ON_MESSAGE_PROP_NAME\n} from 'jsonql-constants'\nimport { CB_FN_NAME } from '../options/constants'\n\nimport { respondHandler } from './respond-handler'\nimport { chainFns, injectToFn, createEvt, toArray, isFunc, isString } from '../utils'\n\n/**\n * Add extra property to the resolver via the getter\n * @param {function} fn the resolver itself\n * @param {object} ee event emitter\n * @param {string} namespace the namespace this belongs to\n * @param {string} resolverName resolver namee\n * @param {object} params from the contract\n * @return {array} same as what goes in\n */\nexport function setupCallbackApi(fn, ee, namespace, resolverName, params) {\n return [\n injectToFn(fn, CB_FN_NAME, function(evtName, callback) {\n if (isString(evtName) && isFunc(callback)) {\n switch(evtName) {\n case RESULT_PROP_NAME:\n ee.$on(\n createEvt(namespace, resolverName, ON_RESULT_PROP_NAME),\n function resultHandler(result) {\n respondHandler(result, callback, (error) => {\n ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error)\n })\n }\n )\n break;\n // register the handler for this message event\n case MESSAGE_PROP_NAME:\n ee.$only(\n createEvt(namespace, resolverName, ON_MESSAGE_PROP_NAME),\n function onMessageCallback(args) {\n respondHandler(args, callback, (error) => {\n ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error)\n })\n }\n )\n break;\n case READY_PROP_NAME:\n ee.$only(\n createEvt(namespace, resolverName, ON_ERROR_PROP_NAME),\n callback\n )\n break;\n default:\n ee.$trigger(\n createEvt(namespace, resolverName, ON_ERROR_PROP_NAME),\n new JsonqlError(resolverName, `Unknown event name ${evtName}!`)\n )\n }\n }\n }),\n ee,\n namespace,\n resolverName,\n params\n ]\n}\n","// break up the original setup resolver method here\nimport { JsonqlValidationError, finalCatch } from 'jsonql-errors'\nimport {\n ERROR_TYPE,\n DATA_KEY,\n ERROR_KEY,\n ON_ERROR_PROP_NAME,\n ON_MESSAGE_PROP_NAME,\n ON_RESULT_PROP_NAME\n} from 'jsonql-constants'\nimport { MY_NAMESPACE } from '../options/constants'\nimport { chainFns, objDefineProps, injectToFn, createEvt, toArray, isFunc } from '../utils'\n\nimport { respondHandler } from './respond-handler'\nimport { setupSend } from './setup-send'\nimport { setupCallbackApi } from './setup-callback-api'\n\n/**\n * The first one in the chain\n * @return {array}\n */\nconst setupNamespace = (fn, ee, namespace, resolverName, params, useCallbackStyle) => [\n injectToFn(fn, MY_NAMESPACE, namespace),\n ee,\n namespace,\n resolverName,\n params,\n useCallbackStyle\n]\n\n// onResult handler\nconst setupOnResult = (fn, ee, namespace, resolverName, params, useCallbackStyle) => [\n objDefineProps(fn, ON_RESULT_PROP_NAME, function(resultCallback) {\n if (isFunc(resultCallback)) {\n ee.$on(\n createEvt(namespace, resolverName, ON_RESULT_PROP_NAME),\n function resultHandler(result) {\n respondHandler(result, resultCallback, (error) => {\n ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error)\n })\n }\n )\n }\n }),\n ee,\n namespace,\n resolverName,\n params,\n useCallbackStyle\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\nconst setupOnMessage = (fn, ee, namespace, resolverName, params, useCallbackStyle) => [\n objDefineProps(fn, ON_MESSAGE_PROP_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 ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error)\n })\n }\n // register the handler for this message event\n ee.$only(createEvt(namespace, resolverName, ON_MESSAGE_PROP_NAME), onMessageCallback)\n }\n }),\n ee,\n namespace,\n resolverName,\n params,\n useCallbackStyle\n]\n\n// add an ON_ERROR_PROP_NAME handler\nconst setupOnError = (fn, ee, namespace, resolverName, params, useCallbackStyle) => [\n objDefineProps(fn, ON_ERROR_PROP_NAME, function(resolverErrorHandler) {\n if (isFunc(resolverErrorHandler)) {\n // please note ON_ERROR_PROP_NAME can add multiple listners\n ee.$only(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), resolverErrorHandler)\n }\n }),\n ee,\n namespace,\n resolverName,\n params,\n useCallbackStyle\n]\n\n/**\n * Add extra property to the resolver\n * @param {string} namespace where this belongs\n * @param {string} resolverName name as event name\n * @param {object} params from contract\n * @param {function} fn resolver function\n * @param {object} ee EventEmitter\n * @param {boolean} useCallbackStyle new callback style\n * @return {function} resolver\n */\nexport function setupResolver(namespace, resolverName, params, fn, ee, useCallbackStyle) {\n // also need to setup a getter to get back the namespace of this resolver\n let args = [setupNamespace]\n useCallbackStyle ? args.push(setupCallbackApi) : args.push(setupOnResult, setupOnMessage, setupOnError)\n args.push(setupSend)\n // get the executor\n const executor = Reflect.apply(chainFns, null, args)\n\n return Reflect.apply(executor, null, [fn, ee, namespace, resolverName, params, useCallbackStyle])\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 { JsonqlError, JsonqlValidationError, finalCatch } from 'jsonql-errors'\nimport { validateAsync } from 'jsonql-params-validator'\nimport {\n ERROR_PROP_NAME,\n LOGIN_PROP_NAME,\n READY_PROP_NAME,\n ON_ERROR_PROP_NAME,\n ON_LOGIN_PROP_NAME,\n ON_READY_PROP_NAME\n} from 'jsonql-constants'\nimport { actionCall } from './action-call'\nimport {\n createEvt,\n toArray,\n injectToFn,\n objDefineProps,\n chainFns,\n isString,\n isFunc,\n isObjectHasKey\n} from '../utils'\nimport { CB_FN_NAME } from '../options/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 {boolean} useCallbackStyle on style or not\n * @return {function} resolver\n */\nexport function createResolver(ee, namespace, resolverName, params, useCallbackStyle) {\n // note we pass the new withResult=true option\n return function(...args) {\n return validateAsync(args, params.params, true)\n .then(_args => actionCall(ee, namespace, resolverName, useCallbackStyle, _args))\n .catch(finalCatch)\n }\n}\n\n/**\n * The problem is the namespace can have more than one\n * and we only have on onError message\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @param {object} nspSet namespace keys\n * @param {boolean} useCallbackStyle use cb or not\n * @return {object} obj with onError prop\n */\nexport function createNamespaceErrorHandler(obj, ee, nspSet) {\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the obj itself\n return objDefineProps(obj, ON_ERROR_PROP_NAME, function namespaceErrorCallbackHandler(namespaceErrorHandler) {\n if (isFunc(namespaceErrorHandler)) {\n // please note ON_ERROR_PROP_NAME can add multiple listners\n for (let namespace in nspSet) {\n // this one is very tricky, we need to make sure the trigger is calling\n // with the namespace as well as the error\n ee.$on(createEvt(namespace, ON_ERROR_PROP_NAME), namespaceErrorHandler)\n }\n }\n })\n}\n\n/**\n * This event will fire when the socket.io.on('connection') and ws.onopen\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @param {object} nspSet namespace keys\n * @return {object} obj with onReady prop\n */\nexport function createOnReadyhandler(obj, ee, nspSet) {\n return objDefineProps(obj, ON_READY_PROP_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_PROP_NAME, onReadyCallback)\n }\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 * @param {object} opts configuration\n * @return {object} obj with onLogin prop\n */\nexport function createOnLoginhandler(obj, ee, opts) {\n if (opts.enableAuth) {\n return objDefineProps(obj, ON_LOGIN_PROP_NAME, function onLoginCallbackHandler(onLoginCallback) {\n if (isFunc(onLoginCallback)) {\n // only one callback can registered with it, TBC\n ee.$only(ON_LOGIN_PROP_NAME, onLoginCallback)\n }\n })\n }\n // just skip it\n return obj\n}\n\n/**\n * when useCallbackStyle=true use this instead of the above method\n * @param {object} obj the base object to attach to\n * @param {object} ee EventEmitter\n * @param {object} nspSet the map\n * @param {object} opts configuration\n * @return {object} obj\n */\nexport function createCallbackHandler(obj, ee, nspSet, opts) {\n return injectToFn(obj, CB_FN_NAME, function onHandler(evtName, callback) {\n if (isString(evtName) && isFunc(callback)) {\n switch (evtName) {\n case ERROR_PROP_NAME:\n for (let namespace in nspSet) {\n // this one is very tricky, we need to make sure the trigger is calling\n // with the namespace as well as the error\n ee.$on(createEvt(namespace, ERROR_PROP_NAME), callback)\n }\n break;\n case LOGIN_PROP_NAME: // @TODO should only available when enableAuth=true\n ee.$only(LOGIN_PROP_NAME, callback)\n break;\n case READY_PROP_NAME:\n ee.$on(READY_PROP_NAME, callback)\n break;\n default:\n ee.$trigger(ERROR_PROP_NAME, new JsonqlError(CB_FN_NAME, `Unknown event name ${evtName}!`))\n }\n }\n // @TODO need to issue another error here!\n })\n}\n","// take out from the resolver-methods\nimport { LOGIN_EVENT_NAME, LOGOUT_EVENT_NAME } from 'jsonql-constants'\nimport { JsonqlValidationError } from 'jsonql-errors'\nimport { injectToFn, chainFns, isString } from '../utils'\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 * break out from createAuthMethods to allow chaining call\n * @param {object} obj the main client object\n * @param {object} ee event emitter\n * @param {object} opts configuration\n * @return {array} modified input\n */\nconst setupLoginHandler = (obj, ee, opts) => [\n injectToFn(obj, opts.loginHandlerName, function loginHandler(token) {\n if (token && isString(token)) {\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 ee,\n opts\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} ee event emitter\n * @param {object} opts configuration\n * @return {object} the modified obj\n */\nconst setupLogoutHandler = (obj, ee, opts) => (\n injectToFn(obj, opts.logoutHandlerName, function logoutHandler(...args) {\n ee.$trigger(LOGOUT_EVENT_NAME, args)\n })\n)\n\n/**\n * Create auth related methods\n * @param {object} obj the client itself\n * @param {object} ee Event Emitter\n * @param {object} opts configuration\n * @return {object} obj with auth methods if any\n */\nexport function createAuthMethods(obj, ee, opts) {\n if (opts.enableAuth) {\n return chainFns(setupLoginHandler, setupLogoutHandler)(obj, ee, opts)\n }\n return obj\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 { setupResolver } from './setup-resolver'\nimport {\n createResolver,\n createNamespaceErrorHandler,\n createOnReadyhandler,\n createOnLoginhandler,\n createCallbackHandler\n} from './resolver-methods'\nimport { createAuthMethods } from './setup-auth-methods'\nimport { injectToFn, chainProcessPromises } from '../utils'\n\n/**\n * step one get the obj map with the namespace\n * @param {object} opts configuration\n * @param {object} nspMap resolvers index by their namespace\n * @param {object} ee EventEmitter\n * @return {promise} resolve the obj mapped, and start the chain\n */\nfunction getMappedObj(opts, nspMap, ee) {\n let obj = {};\n // let resolverNames = [];\n const { nspSet } = nspMap;\n const { useCallbackStyle } = opts; // @1.2.1\n for (let namespace in nspSet) {\n let list = nspSet[namespace]\n for (let resolverName in list) {\n // resolverNames.push(resolverName)\n let params = list[resolverName]\n let fn = createResolver(ee, namespace, resolverName, params, useCallbackStyle)\n // this should set as a getter therefore can not be overwrite by accident\n // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n obj = injectToFn(obj, resolverName, setupResolver(namespace, resolverName, params, fn, ee, useCallbackStyle))\n }\n }\n // move this two method down to helpers\n // we want these methods visible in debug or console.log\n obj.devHelpers = {\n // this is a helper method for the developer to know the namespace inside\n getNsp: () => Object.keys(nspSet),\n // simple get version trick\n getVer: () => opts.version || 'NOT SET'\n // not really necessary because the dev can query the contract\n // getResolverNames: () => resolverNames\n }\n // resolve the obj to start the chain\n // chain the result to allow the chain processing\n return Promise.resolve(obj)\n}\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 generator(opts, nspMap, ee) {\n const { nspSet } = nspMap\n const { useCallbackStyle, enableAuth } = opts;\n let args = [getMappedObj]\n if (useCallbackStyle) {\n args.push(obj => createCallbackHandler(obj, ee, nspSet, opts))\n } else {\n args.push(\n obj1 => createNamespaceErrorHandler(obj1, ee, nspSet),\n obj2 => createOnReadyhandler(obj2, ee, nspSet),\n )\n if (enableAuth) {\n args.push(obj3 => createOnLoginhandler(obj3, ee, opts))\n }\n }\n // this only apply to when enableAuth = true\n if (enableAuth) {\n args.push(obj4 => createAuthMethods(obj4, ee, opts))\n }\n // run it\n const executor = Reflect.apply(chainProcessPromises, null, args)\n return executor(opts, nspMap, ee)\n}\n","// create options\nimport { checkConfigAsync } from 'jsonql-params-validator'\nimport { wsCoreDefaultOptions, wsCoreConstProps } from './defaults'\nimport { fixWss, getHostName } from '../utils'\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 checkOptionsWrapper(config, defaultOptions, constProps) {\n const wsConstProps = Object.assign(wsCoreConstProps, constProps)\n const defaultCheckOptions = Object.assign(wsCoreDefaultOptions, defaultOptions)\n /*\n const fn = postConfigCheck(checkMap, constProps, checkConfig)\n return fn(config)\n */\n return checkConfigAsync(config, defaultCheckOptions, 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 postWsOptions(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 // debug('CONFIGURATION OPTIONS', opts)\n return opts\n })\n}\n\n/**\n * check the configuration\n * @param {object} config user supplied configuration\n * @param {object} defaultOptions the check map\n * @param {object} constProps developer supplied configuration\n * @return {object} after checked\n */\nfunction checkWsCoreOptions(config, defaultOptions, constProps) {\n return checkOptionsWrapper(config, defaultOptions, constProps)\n .then(postWsOptions)\n}\n\n\nexport {\n wsCoreDefaultOptions,\n wsCoreConstProps,\n checkWsCoreOptions,\n postWsOptions\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 { checkWsCoreOptions } from './options'\nimport { ee, processContract } from './utils'\nimport { CHECKED_KEY } from 'jsonql-constants'\n\n/**\n * @TODO remove this implmenetation once the test is done\n */\nconst dummyLogger = (...args) => {\n Reflect.apply(console.info, console, ['[jsonql-ws-client-core]', ...args])\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 log('CHECKED_KEY', opts[CHECKED_KEY])\n if (eventEmitter) {\n log(`eventEmitter is:`, eventEmitter.name)\n return eventEmitter\n }\n log(`Create a new Event Emitter`)\n return new ee( opts.log )\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 opts.log = dummyLogger\n }\n opts.log('--- wsClientCore config opts ---', opts)\n return opts\n}\n\n/**\n * 0.5.0 we break up the wsClientCore in two parts one without the config check \n * @param {function} socketClientResolver \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(socketClientResolver, config) {\n return Promise.resolve(config)\n .then(getLogFn)\n .then(opts => ({\n opts,\n nspMap: processContract(opts),\n ee: getEventEmitter(opts)\n }))\n .then(\n ({opts, nspMap, ee}) => socketClientResolver(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} socketClientResolver this is the one method export by various clients\n * @param {object} [defaultOptions={}] 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 {object} the wsClient instance with all the available API\n */\nexport function wsClientCore(socketClientResolver, defaultOptions = {}, constProps = {}) {\n // we need to inject property to this client later\n // therefore we need to do it this way\n return (config = {}) => (\n checkWsCoreOptions(config, defaultOptions, constProps)\n .then(opts => wsClientCoreAction(socketClientResolver, opts))\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\nconst wsClientAppProps = {}\n\nexport { wsClientAppProps, wsClientConstProps }\n","// pass the different type of ws to generate the client\nimport { TOKEN_PARAM_NAME } from 'jsonql-constants'\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 */\nconst 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 * The bug was in the wsOptions where ws doesn'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 */\nexport function createWsClient(WebSocket, auth = false) {\n if (auth === false) {\n return function createWsClientHandler(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 createWsAuthClientHandler(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","// since both the ws and io version are\n// pre-defined in the client-generator\n// and this one will have the same parameters\n// and the callback is identical\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 } = opts;\n const url = namespace ? [hostname, namespace].join('/') : wssPath;\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 } = opts;\n const url = namespace ? [hostname, namespace].join('/') : wssPath;\n if (token && typeof token !== 'string') {\n throw new Error(`Expect token to be string, but got ${token}`)\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_PROP_NAME, ERROR_PROP_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 * @param {object} opts configuration\n * @return {void}\n */\nexport function triggerNamespacesOnError(ee, namespaces, message, opts = {}) {\n const { useCallbackStyle } = opts;\n const ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME;\n namespaces.forEach( namespace => {\n ee.$call(createEvt(namespace, ERROR_SUBFIX), [{ message, namespace }])\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\nimport {\n ERROR_PROP_NAME,\n RESULT_PROP_NAME,\n // LOGIN_EVENT_NAME,\n LOGOUT_EVENT_NAME,\n NOT_LOGIN_ERR_MSG,\n ON_ERROR_PROP_NAME,\n ON_RESULT_PROP_NAME,\n // ON_MESSAGE_PROP_NAME,\n} from 'jsonql-constants'\nimport { EMIT_EVT, SOCKET_IO, WS } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A fake ee handler\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 { useCallbackStyle, log } = opts;\n const ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME;\n const RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME;\n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n\n log('[notLoginHandler] hijack the ws call', namespace, resolverName, args)\n\n let error = {\n message: NOT_LOGIN_ERR_MSG\n }\n // It should just throw error here and should not call the result\n // because that's channel for handling normal event not the fake one\n ee.$call(createEvt(namespace, resolverName, ERROR_SUBFIX), [error])\n // also trigger the result handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, RESULT_SUBFIX), [{ 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 * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {array} namespaces namespace(s)\n * @param {object} ee Event Emitter instance\n * @param {function} bindWsHandler binding the ee to ws --> this is the core bit\n * @param {array} namespaces array of namespace available\n * @param {object} nsps namespaced nsp\n * @return {void} nothing\n */\nexport function clientEventHandler(opts, nspMap, ee, bindWsHandler, namespaces, nsps) {\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 const { log } = opts;\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run a waterfall here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace;\n if (nsps[namespace]) {\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n if (opts.serverType === SOCKET_IO) {\n let { nspSet } = nspMap;\n args.push(nspSet[namespace])\n }\n Reflect.apply(bindWsHandler, null, args)\n } else {\n // a dummy placeholder\n notLoginWsHandler(namespace, ee, opts)\n }\n })\n // this will be available regardless enableAuth\n // because the server can log the client out\n ee.$on(LOGOUT_EVENT_NAME, function logoutEvtHandler() {\n log('LOGOUT_EVENT_NAME')\n // disconnect(nsps, opts.serverType)\n // we need to issue error to all the namespace onError handler\n triggerNamespacesOnError(ee, namespaces, LOGOUT_EVENT_NAME)\n // rebind all of the handler to the fake one\n namespaces.forEach( namespace => {\n clearMainEmitEvt(ee, namespace)\n // clear out the nsp\n nsps[namespace] = false;\n // add a NOT LOGIN error if call\n notLoginWsHandler(namespace, ee, opts)\n })\n })\n}\n","// take the ws reply data for use\nimport { WS_EVT_NAME, WS_DATA_NAME, WS_REPLY_TYPE } from 'jsonql-constants'\nimport { isString } from 'jsonql-params-validator'\nimport { isObjectHasKey } from 'jsonql-utils/module'\nimport { JsonqlError, clientErrorsHandler } from 'jsonql-errors'\n\nconst keys = [ WS_REPLY_TYPE, WS_EVT_NAME, WS_DATA_NAME ]\n\n/**\n * @param {object} payload should be string when reply but could be transformed\n * @return {boolean} true is OK\n */\nconst isWsReply = payload => {\n const { data } = payload\n if (data) {\n let result = keys.filter(key => isObjectHasKey(data, key))\n return (result.length === keys.length) ? data : false\n }\n return false\n}\n\n/**\n * @param {object} payload This is the entire ws Event Object\n * @return {object} false on failed\n */\nconst extractWsPayload = payload => {\n const { data } = payload;\n let json = isString(data) ? JSON.parse(data) : data\n let fdata;\n if ((fdata = isWsReply(json)) !== false) {\n return {\n resolverName: fdata[WS_EVT_NAME],\n data: fdata[WS_DATA_NAME],\n type: fdata[WS_REPLY_TYPE]\n }\n }\n throw new JsonqlError('payload can not be decoded', payload)\n}\n// export it\nexport default extractWsPayload\n","// the WebSocket main handler\nimport {\n LOGIN_EVENT_NAME,\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_TYPE,\n\n ON_ERROR_PROP_NAME,\n ON_MESSAGE_PROP_NAME,\n ON_RESULT_PROP_NAME,\n ON_READY_PROP_NAME,\n ON_LOGIN_PROP_NAME,\n\n ERROR_PROP_NAME,\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME,\n READY_PROP_NAME,\n LOGIN_PROP_NAME\n} from 'jsonql-constants'\nimport { createQueryStr, createEvt } from 'jsonql-utils/module'\nimport extractWsPayload from './extract-ws-payload'\n\n\n/**\n * under extremely circumstances we might not even have a resolverName, then\n * we issue a global error for the developer to catch it\n * @param {object} ee event emitter\n * @param {string} namespace nsp\n * @param {string} resolverName resolver\n * @param {object} json decoded payload or error object\n * @param {string} ERROR_EVT_NAME the error event name\n * @return {undefined} nothing return\n */\nconst errorTypeHandler = (ee, namespace, resolverName, json, ERROR_EVT_NAME) => {\n let evt = [namespace]\n if (resolverName) {\n evt.push(resolverName)\n }\n evt.push(ERROR_EVT_NAME)\n let evtName = Reflect.apply(createEvt, null, evt)\n // test if there is a data field\n let payload = json.data || json;\n ee.$trigger(evtName, [payload])\n}\n\n/**\n * Binding the even to socket normally\n * @param {string} namespace\n * @param {object} ws the nsp\n * @param {object} ee EventEmitter\n * @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 wsMainHandler(namespace, ws, ee, isPrivate, opts) {\n const { useCallbackStyle, log } = opts;\n\n log(`wsMainHandler log test`)\n\n const READY_EVT_NAME = useCallbackStyle ? READY_PROP_NAME : ON_READY_PROP_NAME;\n const LOGIN_EVT_NAME = useCallbackStyle ? LOGIN_PROP_NAME : ON_LOGIN_PROP_NAME;\n const MESSAGE_EVT_NAME = useCallbackStyle ? MESSAGE_PROP_NAME : ON_MESSAGE_PROP_NAME;\n const RESULT_EVT_NAME = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME;\n const ERROR_EVT_NAME = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME;\n // connection open\n ws.onopen = function onOpenCallback() {\n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(READY_EVT_NAME, namespace)\n // need an extra parameter here to id the private nsp\n if (isPrivate) {\n log(`isPrivate and fire the ${LOGIN_EVT_NAME}`)\n ee.$call(LOGIN_EVT_NAME, namespace)\n }\n // add listener only after the open is called\n ee.$only(\n createEvt(namespace, EMIT_REPLY_TYPE),\n function wsMainOnEvtHandler(resolverName, args) {\n log('calling server', resolverName, args)\n ws.send(\n createQueryStr(resolverName, args)\n )\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 const json = extractWsPayload(payload)\n const { resolverName, type } = json;\n log('Hear from server', type, json)\n switch (type) {\n case EMIT_REPLY_TYPE:\n let e1 = createEvt(namespace, resolverName, MESSAGE_EVT_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, RESULT_EVT_NAME)\n let x = ee.$trigger(e2, [json])\n // log(`ACKNOWLEDGE_REPLY_TYPE`, e2, json)\n break;\n case ERROR_TYPE:\n // this is handled error and we won't throw it\n // we need to extract the error from json\n log(`ERROR_TYPE`)\n errorTypeHandler(ee, namespace, resolverName, json, ERROR_EVT_NAME)\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, ERROR_EVT_NAME)\n // let error = {error: {'message': 'Unhandled event!', type}};\n // ee.$trigger(createEvt(namespace, resolverName, ON_RESULT_PROP_NAME), [error])\n }\n } catch(e) {\n console.error(`ws.onmessage error`, e)\n errorTypeHandler(ee, namespace, false, e, ERROR_EVT_NAME)\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 // listen to the LOGOUT_EVENT_NAME\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","// actually binding the event client to the socket client\nimport { getNameFromPayload, getNamespaceInOrder } from 'jsonql-utils/module'\nimport { LOGIN_EVENT_NAME, LOGOUT_EVENT_NAME, JS_WS_NAME } from 'jsonql-constants'\nimport {\n createNspClient,\n createNspAuthClient,\n clientEventHandler,\n // comment them out for now they are not in use\n // triggerNamespacesOnError,\n // disconnect\n clearMainEmitEvt\n} from 'jsonql-ws-client-core/share'\nimport { wsMainHandler } from './ws-main-handler'\n\n/**\n * Because the nsps can be throw away so it doesn't matter the scope\n * this will get reuse again\n * @param {object} opts configuration\n * @param {object} nspMap from contract\n * @param {string|null} token whether we have the token at run time\n * @return {object} nsps namespace with namespace as key\n */\nconst createNsps = function(opts, nspMap, token) {\n let { nspSet, publicNamespace } = nspMap\n let login = false\n let namespaces = []\n let nsps = {}\n // first we need to binding all the events handler\n if (opts.enableAuth) { // && opts.useJwt\n login = true; // just saying we need to listen to login event\n namespaces = getNamespaceInOrder(nspSet, publicNamespace)\n nsps = namespaces.map((namespace, i) => {\n if (i === 0) {\n if (token) {\n opts.token = token\n // console.log('create createNspAuthClient at run time', opts)\n return {[namespace]: createNspAuthClient(namespace, opts)}\n }\n return {[namespace]: false}\n }\n return {[namespace]: createNspClient(namespace, opts)}\n }).reduce((first, next) => Object.assign(first, next), {})\n } else {\n let namespace = getNameFromPayload(nspSet)\n namespaces.push(namespace)\n // standard without login\n // the stock version should not have a namespace\n nsps[namespace] = createNspClient(false, opts)\n }\n // return\n return { nsps, namespaces, login }\n}\n\n/**\n * create a ws client\n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nexport function createClient(opts, nspMap, ee) {\n // arguments that don't change\n const args = [opts, nspMap, ee, wsMainHandler]\n // now create the nsps\n const { token, log } = opts\n const { nsps, namespaces, login } = createNsps(opts, nspMap, token)\n // binding the listeners - and it will listen to LOGOUT event\n // to unbind itself, and the above call will bind it again\n Reflect.apply(clientEventHandler, null, args.concat([namespaces, nsps]))\n // setup listener\n if (login) {\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandler(tokenLater) {\n\n log('createClient LOGIN_EVENT_NAME')\n\n // debugFn(`LOGIN_EVENT_NAME called with token:`, tokenLater)\n // @BUG 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\n // disconnect(nsps, JS_WS_NAME)\n\n // @TODO should we trigger error on this one?\n // triggerNamespacesOnError(ee, namespaces, LOGIN_EVENT_NAME)\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNsps(opts, nspMap, tokenLater)\n // rebind it\n Reflect.apply(\n clientEventHandler,\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\n }\n // return what input\n return { opts, nspMap, ee }\n}\n","// share method to create the wsClientResolver\n\nimport { createWsClient } from './create-ws-client'\nimport { createClient } from './create-client'\n\n/**\n * combine the create client resolver\n * @param {object} ws the different WebSocket module\n * @return {function} the wsClientResolver\n */\nexport default function createClientResolver(ws) {\n const client = createWsClient(ws)\n const authClient = createWsClient(ws, true)\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(opts, nspMap, ee) {\n opts.nspClient = client;\n opts.nspAuthClient = authClient;\n // @1.0.7 remove later once everything fixed \n const { log } = opts;\n if (log && typeof log === 'function') {\n log('@jsonql/ws ee', ee.name)\n log('@jsonql/ws createClientResolver', opts)\n }\n // console.log(`contract`, opts.contract)\n return createClient(opts, nspMap, ee)\n }\n}\n","// 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 createClientResolver from './core/create-client-resolver'\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 createClientResolver(WebSocket)\n","// this is the module entry point for node\nimport { wsClientCore } from 'jsonql-ws-client-core'\nimport { wsClientAppProps, wsClientConstProps } from './options'\nimport wsClientResolver from './node-ws-client-resolver'\n\n// export back the function and that's it\nexport default function wsBrowserClient(config = {}, constProps = {}) {\n const initMethod = wsClientCore(wsClientResolver, wsClientAppProps, Object.assign(wsClientConstProps, constProps))\n return initMethod(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;;;;;;;;;;;;;"} \ No newline at end of file +{"version":3,"file":"main.js","sources":[],"sourcesContent":[],"names":[],"mappings":""} \ No newline at end of file diff --git a/packages/@jsonql/ws/module.js b/packages/@jsonql/ws/module.js index 7098be55..a88c8e6d 100644 --- a/packages/@jsonql/ws/module.js +++ b/packages/@jsonql/ws/module.js @@ -1,6 +1,5 @@ // this is a new interface that takes the already check config // and init the ws client - import { wsCoreDefaultOptions, wsCoreConstProps, @@ -11,4 +10,6 @@ import { // import { jsonqlWsClientCore } from 'jsonql-ws-client-core' import wsClientResolver from './src/ws-client-resolver' -import { wsClientAppProps, wsClientConstProps } from './src/options' \ No newline at end of file +import { wsClientAppProps, wsClientConstProps } from './src/options' + + diff --git a/packages/@jsonql/ws/package.json b/packages/@jsonql/ws/package.json index 1d6740e2..7cd6a741 100644 --- a/packages/@jsonql/ws/package.json +++ b/packages/@jsonql/ws/package.json @@ -20,7 +20,6 @@ "build:cjs": "TARGET=cjs rollup -c", "build:umd": "TARGET=umd rollup -c", "build:cjs:module": "TARGET=cjs-module rollup -c", - "build:umd:module": "TARGET=umd-module rollup -c", "build:test": "npm run build:cjs && npm run build:umd && npm run build:cjs:module && npm run build:umd:module", "build": "NODE_ENV=production npm run build:cjs && NODE_ENV=production npm run build:umd", "test:browser:basic": "npm run build:umd && DEBUG=jsonql-ws-client*,server-io-core* node ./tests/browser/run-qunit.js", diff --git a/packages/@jsonql/ws/rollup.config.js b/packages/@jsonql/ws/rollup.config.js index 125031e3..5d753bca 100644 --- a/packages/@jsonql/ws/rollup.config.js +++ b/packages/@jsonql/ws/rollup.config.js @@ -51,14 +51,23 @@ if (process.env.NODE_ENV === 'production') { } plugins.push( size() ) -// @TODO there will be more and need to change how this take the file -const inFile = target === 'cjs' ? 'src/node.js' : 'index.js' -const outFile = target === 'cjs' - ? join(__dirname, 'main.js') - : join(__dirname, 'dist', `jsonql-ws-client.${target}.js`) - - +let inFile, outFile +switch (target) { + case 'cjs': + inFile = 'src/node.js' + outFile = join(__dirname, 'main.js') + break + case 'cjs-module': + inFile = 'module.js' + outFile = join(__dirname, 'node.js') + break + case 'umd': + default: + inFile = 'index.js' + outFile = join(__dirname, 'dist', `jsonql-ws-client.${target}.js`) + break +} let config = { input: join(__dirname, inFile), -- Gitee From 8f4ed4101f5c01b40568936a48b33f7183440de4 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 4 Mar 2020 00:26:52 +0800 Subject: [PATCH 21/26] End of day commit --- packages/@jsonql/ws/index.js | 13 +++++++++--- packages/@jsonql/ws/module.js | 21 ++++++++++++++++++-- packages/ws-client-core/src/options/index.js | 1 - 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/packages/@jsonql/ws/index.js b/packages/@jsonql/ws/index.js index 926dc0af..68901483 100644 --- a/packages/@jsonql/ws/index.js +++ b/packages/@jsonql/ws/index.js @@ -1,7 +1,10 @@ // this is the module entry point for ES6 for client // the main will point to the node.js server side setup - -import { wsClientCore } from '../../ws-client-core' +import { + wsCoreDefaultOptions, + wsCoreConstProps, + wsClientCore +} from '../../ws-client-core' // 'jsonql-ws-client-core' import wsClientResolver from './src/ws-client-resolver' @@ -9,6 +12,10 @@ import { wsClientAppProps, wsClientConstProps } from './src/options' // export back the function and that's it export default function wsBrowserClient(config = {}, constProps = {}) { - const initMethod = wsClientCore(wsClientResolver, wsClientAppProps, Object.assign(wsClientConstProps, constProps)) + const initMethod = wsClientCore( + wsClientResolver, + Object.assign({}, wsCoreDefaultOptions, wsClientAppProps), + Object.assign({}, wsCoreConstProps, wsClientConstProps, constProps) + ) return initMethod(config) } diff --git a/packages/@jsonql/ws/module.js b/packages/@jsonql/ws/module.js index a88c8e6d..956f931f 100644 --- a/packages/@jsonql/ws/module.js +++ b/packages/@jsonql/ws/module.js @@ -7,9 +7,26 @@ import { wsClientCoreAction } from 'jsonql-ws-client-core' -// import { jsonqlWsClientCore } from 'jsonql-ws-client-core' - import wsClientResolver from './src/ws-client-resolver' import { wsClientAppProps, wsClientConstProps } from './src/options' +const jsonqlWsClientAppProps = Object.assign({}, wsCoreDefaultOptions, wsClientAppProps) +const jsonqlWsConstProps = Object.assign({}, wsCoreConstProps, wsClientConstProps) + +/** + * Take the already checked options (using part of export here) + * then generate the ws client + * @param {*} config + */ +function createWsClient(config) { + return Promise.resolve(config) + .then(postWsOptions) + .then(opts => wsClientCoreAction(wsClientResolver, opts)) +} +// export +export { + jsonqlWsClientAppProps, + jsonqlWsConstProps, + createWsClient +} diff --git a/packages/ws-client-core/src/options/index.js b/packages/ws-client-core/src/options/index.js index e16401a1..a0545608 100644 --- a/packages/ws-client-core/src/options/index.js +++ b/packages/ws-client-core/src/options/index.js @@ -51,7 +51,6 @@ function checkWsCoreOptions(config, defaultOptions, constProps) { .then(postWsOptions) } - export { wsCoreDefaultOptions, wsCoreConstProps, -- Gitee From 4b91e489f5fd26c4a1d7a7d24008d33d5aaa6807 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 4 Mar 2020 07:59:50 +0800 Subject: [PATCH 22/26] finalize on the module interface --- packages/@jsonql/ws/module.js | 27 +++++------------- packages/@jsonql/ws/rollup.config.js | 2 +- packages/@jsonql/ws/src/module.js | 38 ++++++++++++++++++++++++++ packages/@jsonql/ws/src/node-module.js | 16 +++++++++++ 4 files changed, 62 insertions(+), 21 deletions(-) create mode 100644 packages/@jsonql/ws/src/module.js create mode 100644 packages/@jsonql/ws/src/node-module.js diff --git a/packages/@jsonql/ws/module.js b/packages/@jsonql/ws/module.js index 956f931f..215979db 100644 --- a/packages/@jsonql/ws/module.js +++ b/packages/@jsonql/ws/module.js @@ -1,30 +1,17 @@ // this is a new interface that takes the already check config // and init the ws client -import { - wsCoreDefaultOptions, - wsCoreConstProps, - postWsOptions, - wsClientCoreAction -} from 'jsonql-ws-client-core' import wsClientResolver from './src/ws-client-resolver' -import { wsClientAppProps, wsClientConstProps } from './src/options' -const jsonqlWsClientAppProps = Object.assign({}, wsCoreDefaultOptions, wsClientAppProps) -const jsonqlWsConstProps = Object.assign({}, wsCoreConstProps, wsClientConstProps) +import { + jsonqlWsClientAppProps, + jsonqlWsConstProps, + generateWsClient +} from './src/module' -/** - * Take the already checked options (using part of export here) - * then generate the ws client - * @param {*} config - */ -function createWsClient(config) { - return Promise.resolve(config) - .then(postWsOptions) - .then(opts => wsClientCoreAction(wsClientResolver, opts)) -} +const createWsClient = generateWsClient(wsClientResolver) -// export +// export done export { jsonqlWsClientAppProps, jsonqlWsConstProps, diff --git a/packages/@jsonql/ws/rollup.config.js b/packages/@jsonql/ws/rollup.config.js index 5d753bca..2266c5c6 100644 --- a/packages/@jsonql/ws/rollup.config.js +++ b/packages/@jsonql/ws/rollup.config.js @@ -59,7 +59,7 @@ switch (target) { outFile = join(__dirname, 'main.js') break case 'cjs-module': - inFile = 'module.js' + inFile = 'src/node-module.js' outFile = join(__dirname, 'node.js') break case 'umd': diff --git a/packages/@jsonql/ws/src/module.js b/packages/@jsonql/ws/src/module.js new file mode 100644 index 00000000..42f41be5 --- /dev/null +++ b/packages/@jsonql/ws/src/module.js @@ -0,0 +1,38 @@ +// this is the module version without checking the config +// The different between browser and node is the following +// so we just need to supply it then create the method and export +// then the other module take the props, run config check then pass back +// here and they get their own ws client +// import wsClientResolver from './node-ws-client-resolver' + +import { + wsCoreDefaultOptions, + wsCoreConstProps, + postWsOptions, + wsClientCoreAction +} from 'jsonql-ws-client-core' + +import { wsClientAppProps, wsClientConstProps } from './options' + +const jsonqlWsClientAppProps = Object.assign({}, wsCoreDefaultOptions, wsClientAppProps) +const jsonqlWsConstProps = Object.assign({}, wsCoreConstProps, wsClientConstProps) + +/** + * Take the already checked options (using part of export here) + * then generate the ws client + * @param {function} wsClientResolver configuration + * @return {function} take config return the promise resolve the ws client + */ +function generateWsClient(wsClientResolver) { + return (config) => Promise + .resolve(config) + .then(postWsOptions) + .then(opts => wsClientCoreAction(wsClientResolver, opts)) +} + +// export +export { + jsonqlWsClientAppProps, + jsonqlWsConstProps, + generateWsClient +} \ No newline at end of file diff --git a/packages/@jsonql/ws/src/node-module.js b/packages/@jsonql/ws/src/node-module.js new file mode 100644 index 00000000..b1a9d3b4 --- /dev/null +++ b/packages/@jsonql/ws/src/node-module.js @@ -0,0 +1,16 @@ +// modular client creation for node +import nodeWsClientResolver from './node-ws-client-resolver' +import { + jsonqlWsClientAppProps, + jsonqlWsConstProps, + generateWsClient +} from './src/module' + +const createWsClient = generateWsClient(nodeWsClientResolver) + +// export done +export { + jsonqlWsClientAppProps, + jsonqlWsConstProps, + createWsClient +} \ No newline at end of file -- Gitee From 4f6af5127c187a0c69a54dfa162a82988b0440eb Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 4 Mar 2020 08:04:21 +0800 Subject: [PATCH 23/26] Fix the build script --- packages/@jsonql/ws/dist/jsonql-ws-client.umd.js | 2 +- packages/@jsonql/ws/node.js | 2 ++ packages/@jsonql/ws/node.js.map | 1 + packages/@jsonql/ws/package.json | 2 +- packages/@jsonql/ws/rollup.config.js | 7 +++++-- packages/@jsonql/ws/src/node-module.js | 2 +- 6 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 packages/@jsonql/ws/node.js create mode 100644 packages/@jsonql/ws/node.js.map diff --git a/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js b/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js index 0cc7ccbc..684f734b 100644 --- a/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js +++ b/packages/@jsonql/ws/dist/jsonql-ws-client.umd.js @@ -1,2 +1,2 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).jsonqlWsClient=e()}(this,(function(){"use strict";var t="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},e="object"==typeof t&&t&&t.Object===Object&&t,r="object"==typeof self&&self&&self.Object===Object&&self,n=e||r||Function("return this")(),o=n.Symbol;function u(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var u=Array(o);++n-1;);return r}(n,o),function(t,e){for(var r=t.length;r--&&j(e,t[r],0)>-1;);return r}(n,o)+1).join("")}var M=function(t){return!!i(t)||null!=t&&""!==R(t)};function F(t){return function(t){return"number"==typeof t||v(t)&&"[object Number]"==h(t)}(t)&&t!=+t}function L(t){return"string"==typeof t||!i(t)&&v(t)&&"[object String]"==h(t)}var W=function(t){return!L(t)&&!F(parseFloat(t))},J=function(t){return""!==R(t)&&L(t)},I=function(t){return null!=t&&"boolean"==typeof t},D=function(t,e){return void 0===e&&(e=!0),void 0!==t&&""!==t&&""!==R(t)&&(!1===e||!0===e&&null!==t)},U=function(t){switch(t){case"number":return W;case"string":return J;case"boolean":return I;default:return D}},V=function(t,e){return void 0===e&&(e=""),!!i(t)&&(""===e||""===R(e)||!(t.filter((function(t){return!U(e)(t)})).length>0))},B=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var e=t.replace("array.<","").replace(">","");return e.indexOf("|")?e.split("|"):[e]}return!1},H=function(t,e){var r=t.arg;return e.length>1?!r.filter((function(t){return!(e.length>e.filter((function(e){return!U(e)(t)})).length)})).length:e.length>e.filter((function(t){return!V(r,t)})).length};function Y(t,e){return function(r){return t(e(r))}}var G=Y(Object.getPrototypeOf,Object),K=Function.prototype,Q=Object.prototype,X=K.toString,Z=Q.hasOwnProperty,tt=X.call(Object);function et(t){if(!v(t)||"[object Object]"!=h(t))return!1;var e=G(t);if(null===e)return!0;var r=Z.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&X.call(r)==tt}var rt,nt=function(t,e,r){for(var n=-1,o=Object(t),u=r(t),i=u.length;i--;){var a=u[rt?i:++n];if(!1===e(o[a],a,o))break}return t};function ot(t){return v(t)&&"[object Arguments]"==h(t)}var ut=Object.prototype,it=ut.hasOwnProperty,at=ut.propertyIsEnumerable,ct=ot(function(){return arguments}())?ot:function(t){return v(t)&&it.call(t,"callee")&&!at.call(t,"callee")};var ft="object"==typeof exports&&exports&&!exports.nodeType&&exports,st=ft&&"object"==typeof module&&module&&!module.nodeType&&module,lt=st&&st.exports===ft?n.Buffer:void 0,pt=(lt?lt.isBuffer:void 0)||function(){return!1},ht=/^(?:0|[1-9]\d*)$/;function vt(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&ht.test(t))&&t>-1&&t%1==0&&t-1&&t%1==0&&t<=9007199254740991}var dt={};dt["[object Float32Array]"]=dt["[object Float64Array]"]=dt["[object Int8Array]"]=dt["[object Int16Array]"]=dt["[object Int32Array]"]=dt["[object Uint8Array]"]=dt["[object Uint8ClampedArray]"]=dt["[object Uint16Array]"]=dt["[object Uint32Array]"]=!0,dt["[object Arguments]"]=dt["[object Array]"]=dt["[object ArrayBuffer]"]=dt["[object Boolean]"]=dt["[object DataView]"]=dt["[object Date]"]=dt["[object Error]"]=dt["[object Function]"]=dt["[object Map]"]=dt["[object Number]"]=dt["[object Object]"]=dt["[object RegExp]"]=dt["[object Set]"]=dt["[object String]"]=dt["[object WeakMap]"]=!1;var yt,bt="object"==typeof exports&&exports&&!exports.nodeType&&exports,_t=bt&&"object"==typeof module&&module&&!module.nodeType&&module,mt=_t&&_t.exports===bt&&e.process,jt=function(){try{var t=_t&&_t.require&&_t.require("util").types;return t||mt&&mt.binding&&mt.binding("util")}catch(t){}}(),wt=jt&&jt.isTypedArray,St=wt?(yt=wt,function(t){return yt(t)}):function(t){return v(t)&>(t.length)&&!!dt[h(t)]},Ot=Object.prototype.hasOwnProperty;function kt(t,e){var r=i(t),n=!r&&ct(t),o=!r&&!n&&pt(t),u=!r&&!n&&!o&&St(t),a=r||n||o||u,c=a?function(t,e){for(var r=-1,n=Array(t);++r-1},Ft.prototype.set=function(t,e){var r=this.__data__,n=Rt(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};var Lt,Wt=n["__core-js_shared__"],Jt=(Lt=/[^.]+$/.exec(Wt&&Wt.keys&&Wt.keys.IE_PROTO||""))?"Symbol(src)_1."+Lt:"";var It=Function.prototype.toString;function Dt(t){if(null!=t){try{return It.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var Ut=/^\[object .+?Constructor\]$/,Vt=Function.prototype,Bt=Object.prototype,Ht=Vt.toString,Yt=Bt.hasOwnProperty,Gt=RegExp("^"+Ht.call(Yt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function Kt(t){return!(!Pt(t)||function(t){return!!Jt&&Jt in t}(t))&&(qt(t)?Gt:Ut).test(Dt(t))}function Qt(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return Kt(r)?r:void 0}var Xt=Qt(n,"Map"),Zt=Qt(Object,"create");var te=Object.prototype.hasOwnProperty;var ee=Object.prototype.hasOwnProperty;function re(t){var e=-1,r=null==t?0:t.length;for(this.clear();++ea))return!1;var f=u.get(t);if(f&&u.get(e))return f==e;var s=-1,l=!0,p=2&r?new ie:void 0;for(u.set(t,e),u.set(e,t);++se.type.filter((function(t){var e;return void 0===r||(!1!==(e=B(t))?!H({arg:r},e):!U(t)(r))})).length)})).length}return!1},rr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 406},r.name.get=function(){return"Jsonql406Error"},Object.defineProperties(e,r),e}(Error),nr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"Jsonql500Error"},Object.defineProperties(e,r),e}(Error),or=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 403},r.name.get=function(){return"JsonqlForbiddenError"},Object.defineProperties(e,r),e}(Error),ur=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlAuthorisationError"},Object.defineProperties(e,r),e}(Error),ir=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlContractAuthError"},Object.defineProperties(e,r),e}(Error),ar=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"JsonqlResolverAppError"},Object.defineProperties(e,r),e}(Error),cr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 404},r.name.get=function(){return"JsonqlResolverNotFoundError"},Object.defineProperties(e,r),e}(Error),fr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlEnumError"},Object.defineProperties(e,r),e}(Error),sr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlTypeError"},Object.defineProperties(e,r),e}(Error),lr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlCheckerError"},Object.defineProperties(e,r),e}(Error),pr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(e,r),e}(Error),hr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0},statusCode:{configurable:!0}};return r.name.get=function(){return"JsonqlError"},r.statusCode.get=function(){return-1},Object.defineProperties(e,r),e}(Error),vr=function(t){function e(r,n){t.call(this,n),this.statusCode=r,this.className=e.name}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlServerError"},Object.defineProperties(e,r),e}(Error);function gr(t){if(Array.isArray(t))throw new pr("",t);var e=t.message||"No message",r=t.detail||t;switch(!0){case t instanceof rr:throw new rr(e,r);case t instanceof nr:throw new nr(e,r);case t instanceof or:throw new or(e,r);case t instanceof ur:throw new ur(e,r);case t instanceof ir:throw new ir(e,r);case t instanceof ar:throw new ar(e,r);case t instanceof cr:throw new cr(e,r);case t instanceof fr:throw new fr(e,r);case t instanceof sr:throw new sr(e,r);case t instanceof lr:throw new lr(e,r);case t instanceof pr:throw new pr(e,r);case t instanceof vr:throw new vr(e,r);default:throw new hr(e,r)}}var dr=function(t,e){var r,n,o,u,i;switch(!0){case"object"===t:return o=(n=e).arg,u=n.param,i=[o],Array.isArray(u.keys)&&u.keys.length&&i.push(u.keys),!Reflect.apply(er,null,i);case"array"===t:return!V(e.arg);case!1!==(r=B(t)):return!H(e,r);default:return!U(t)(e.arg)}},yr=function(t,e){return void 0!==t?t:!0===e.optional&&void 0!==e.defaultvalue?e.defaultvalue:null},br=function(t,e,r){var n;void 0===r&&(r=!1);var o=function(t,e){if(!V(e))throw new hr("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===e.length)return[];if(!V(t))throw new hr("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==e.length:return t.map((function(t,r){return{arg:t,index:r,param:e[r]}}));case!0===e[0].variable:var r=e[0].type;return t.map((function(t,n){return{arg:t,index:n,param:e[n]||{type:r,name:"_"}}}));case t.lengthe.length:var n=e.length,o=["any"];return t.map((function(t,r){var u=r>=n||!!e[r].optional,i=e[r]||{type:o,name:"_"+r};return{arg:u?yr(t,i):t,index:r,param:i,optional:u}}));default:throw new hr("Could not understand your arguments and parameter structure!",{args:t,params:e})}}(t,e),u=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var e=t.arg,r=t.param;return!!M(e)&&!(r.type.length>r.type.filter((function(e){return dr(e,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(e){return dr(e,t)})).length)}));return r?((n={}).error=u,n.data=o.map((function(t){return t.arg})),n):u},_r=function(){try{var t=Qt(Object,"defineProperty");return t({},"",{}),t}catch(t){}}();function mr(t,e,r){"__proto__"==e&&_r?_r(t,e,{configurable:!0,enumerable:!0,value:r,writable:!0}):t[e]=r}function jr(t,e,r){(void 0===r||Ct(t[e],r))&&(void 0!==r||e in t)||mr(t,e,r)}var wr="object"==typeof exports&&exports&&!exports.nodeType&&exports,Sr=wr&&"object"==typeof module&&module&&!module.nodeType&&module,Or=Sr&&Sr.exports===wr?n.Buffer:void 0,kr=Or?Or.allocUnsafe:void 0;function Er(t,e){var r,n,o=e?(r=t.buffer,n=new r.constructor(r.byteLength),new fe(n).set(new fe(r)),n):t.buffer;return new t.constructor(o,t.byteOffset,t.length)}var $r=Object.create,Tr=function(){function t(){}return function(e){if(!Pt(e))return{};if($r)return $r(e);t.prototype=e;var r=new t;return t.prototype=void 0,r}}();function Ar(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var Pr=Object.prototype.hasOwnProperty;function qr(t,e,r){var n=t[e];Pr.call(t,e)&&Ct(n,r)&&(void 0!==r||e in t)||mr(t,e,r)}var zr=Object.prototype.hasOwnProperty;function Nr(t){if(!Pt(t))return function(t){var e=[];if(null!=t)for(var r in Object(t))e.push(r);return e}(t);var e=$t(t),r=[];for(var n in t)("constructor"!=n||!e&&zr.call(t,n))&&r.push(n);return r}function xr(t){return zt(t)?kt(t,!0):Nr(t)}function Cr(t){return function(t,e,r,n){var o=!r;r||(r={});for(var u=-1,i=e.length;++u0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(Wr);function Dr(t,e){return Ir(function(t,e,r){return e=Lr(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,u=Lr(n.length-e,0),i=Array(u);++o1?e[n-1]:void 0,u=n>2?e[2]:void 0;for(o=Ur.length>3&&"function"==typeof o?(n--,o):void 0,u&&function(t,e,r){if(!Pt(r))return!1;var n=typeof e;return!!("number"==n?zt(r)&&vt(e,r.length):"string"==n&&e in r)&&Ct(r[e],t)}(e[0],e[1],u)&&(o=n<3?void 0:o,n=1),t=Object(t);++r0?Array.from(this.queueStore):[]},hn.prototype.release=function(){var t=this,e=this.queueStore.size;if(this.logger("(release)","Release was called "+e),e>0){var r=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",r),r.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(hn.prototype,vn);var gn=function(t){function e(e){if("function"!=typeof e)throw new Error("Just die here the logger is not a function!");t.call(this,{logger:e})}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(e.prototype,r),e}(function(t){function e(e){void 0===e&&(e={}),t.call(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={$done:{configurable:!0}};return e.prototype.logger=function(){},e.prototype.$on=function(t,e,r){var n=this;void 0===r&&(r=null);this.validate(t,e);var o=this.takeFromStore(t);if(!1===o)return this.logger("($on)",t+" callback is not in lazy store"),this.addToNormalStore(t,"on",e,r);this.logger("($on)",t+" found in lazy store");var u=0;return o.forEach((function(o){var i=o[0],a=o[1],c=o[2];if(c&&"on"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);n.logger("($on)","call run on "+t),n.run(e,i,r||a),u+=n.addToNormalStore(t,"on",e,r||a)})),u},e.prototype.$once=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=this.takeFromStore(t);this.normalStore;if(!1===n)return this.logger("($once)",t+" not in the lazy store"),this.addToNormalStore(t,"once",e,r);this.logger("($once)",n);var o=Array.from(n)[0],u=o[0],i=o[1],a=o[2];if(a&&"once"!==a)throw new Error("You are trying to register an event already been taken by other type: "+a);this.logger("($once)","call run for "+t),this.run(e,u,r||i),this.$off(t)},e.prototype.$only=function(t,e,r){var n=this;void 0===r&&(r=null),this.validate(t,e);var o=!1,u=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger("($only)",t+" add to store"),o=this.addToNormalStore(t,"only",e,r)),!1!==u)&&(this.logger("($only)",t+" found data in lazy store to execute"),Array.from(u).forEach((function(o){var u=o[0],i=o[1],a=o[2];if(a&&"only"!==a)throw new Error("You are trying to register an event already been taken by other type: "+a);n.logger("($only)","call run for "+t),n.run(e,u,r||i)})));return o},e.prototype.$onlyOnce=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=!1,o=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger("($onlyOnce)",t+" add to store"),n=this.addToNormalStore(t,"onlyOnce",e,r)),!1!==o){this.logger("($onlyOnce)",o);var u=Array.from(o)[0],i=u[0],a=u[1],c=u[2];if(c&&"onlyOnce"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);this.logger("($onlyOnce)","call run for "+t),this.run(e,i,r||a),this.$off(t)}return n},e.prototype.$replace=function(t,e,r,n){if(void 0===r&&(r=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,e),Reflect.apply(o,this,[t,e,r])}throw new Error(n+" is not supported!")},e.prototype.$trigger=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,u=this.normalStore;if(this.logger("($trigger)","normalStore",u),u.has(t)){var i=this.$queue(t,e,r,n);if(this.logger("($trigger)",t,"found; add to queue: ",i),!0===i)return this.logger("($trigger)",t,"not executed. Exit now."),!1;for(var a=Array.from(u.get(t)),c=a.length,f=!1,s=0;s0;)n[o]=arguments[o+2];if(t.has(e)?(this.logger("(addToStore)",e+" existed"),r=t.get(e)):(this.logger("(addToStore)","create new Set for "+e),r=new Set),n.length>2)if(Array.isArray(n[0])){var u=n[2];this.checkTypeInLazyStore(e,u)||r.add(n)}else this.checkContentExist(n,r)||(this.logger("(addToStore)","insert new",n),r.add(n));else r.add(n);return t.set(e,r),[t,r.size]},e.prototype.checkContentExist=function(t,e){return!!Array.from(e).filter((function(e){return e[0]===t[0]})).length},e.prototype.checkTypeInStore=function(t,e){this.validateEvt(t,e);var r=this.$get(t,!0);return!1===r||!r.filter((function(t){var r=t[3];return e!==r})).length},e.prototype.checkTypeInLazyStore=function(t,e){this.validateEvt(t,e);var r=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",r),!!r&&!!Array.from(r).filter((function(t){return t[2]!==e})).length},e.prototype.addToNormalStore=function(t,e,r,n){if(void 0===n&&(n=null),this.logger("(addToNormalStore)",t,e,"try to add to normal store"),this.checkTypeInStore(t,e)){this.logger("(addToNormalStore)",e+" can add to "+t+" normal store");var o=this.hashFnToKey(r),u=[this.normalStore,t,o,r,n,e],i=Reflect.apply(this.addToStore,this,u),a=i[0],c=i[1];return this.normalStore=a,c}return!1},e.prototype.addToLazyStore=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(e),r];n&&o.push(n);var u=Reflect.apply(this.addToStore,this,o),i=u[0],a=u[1];return this.lazyStore=i,a},e.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},r.normalStore.set=function(t){ln.set(this,t)},r.normalStore.get=function(){return ln.get(this)},r.lazyStore.set=function(t){pn.set(this,t)},r.lazyStore.get=function(){return pn.get(this)},e.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,e){return(t=(t<<5)-t+e.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(e.prototype,r),e}(hn))),dn=function(t){var e=t.log,r=t.eventEmitter;return r?(e("eventEmitter is:",r.name),r):(e("Create a new Event Emitter"),new gn(t.log))},yn=function(t){return i(t)?t:[t]},bn=function(t,e){try{var r=Object.keys(t);return n=e,!!r.filter((function(t){return t===n})).length}catch(t){return!1}var n},_n=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return t.join("_")},mn=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},jn=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return Reflect.apply(e,null,yn(t))}),Reflect.apply(t,null,r))}};function wn(t,e,r,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,e)&&Object.defineProperty(t,e,{set:r,get:null===n?function(){return null}:n}),t}function Sn(t,e,r,n){void 0===n&&(n=!1);var o=function(t,e){var r=Object.getOwnPropertyDescriptor(t,e);return void 0!==r&&r.value?r.value:r}(t,e);return!1===n&&void 0!==o||Object.defineProperty(t,e,{value:r,writable:n}),t}function On(t){return!!bn(t,"socket")&&t.socket}function kn(t){var e,r,n=t.contract;return t.enableAuth?function(t,e){void 0===e&&(e=!1);var r=On(t);if(!1===r){if(e)return t;throw new hr("socket not found in contract!")}var n,o={},u=0;for(var i in r){var a=r[i],c=a.namespace;c&&(o[c]||(++u,o[c]={}),o[c][i]=a,n||a.public&&(n=c))}return{size:u,nspSet:o,publicNamespace:n}}(n):((r={}).nspSet=((e={}).jsonql=function(t){var e=On(t);if(!1!==e)return e;throw new cr("Missing property in contract!")}(n),e),r.publicNamespace="jsonql",r)}var En=function(t,e,r){return[Sn(t,e.loginHandlerName,(function(t){if(t&&on(t))return r.$trigger("__login__",[t]);throw new pr(e.loginHandlerName,"Unexpected token "+t)})),r,e]},$n=function(t,e,r){return[Sn(t,e.logoutHandlerName,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__logout__",t)})),r]};function Tn(t,e){return objDefineProps(t,"onLogin",(function(t){isFunc(t)&&e.$only("onLogin",t)}))}function An(t,e,r){return jn(En,$n,Tn)(t,e,r)}function Pn(t,e,r){bn(t,"error")?r(t.error):bn(t,"data")?e(t.data):r({message:"UKNNOWN RESULT!",error:t})}function qn(t,e,r,n){void 0===n&&(n=[]);var o=_n(e,"emit");return debugFn("actionCall: "+o+" --\x3e "+r,n),t.$trigger(o,[r,yn(n)]),new Promise((function(n,o){t.$on(_n(e,r,"onResult"),(function(t){debugFn("got the first result",t),Pn(t,n,o)}))}))}var zn,Nn,xn=function(t,e,r,n,o){return wn(t,"send",(function(t){un(yn(t),o.params,!0).then((function(o){if(!o.error||!o.error.length)return qn(e,r,n,t);e.$call(_n(r,n,"onError"),[new pr(n,o.error)])})).catch((function(t){e.$call(_n(r,n,"onError"),[new pr(n,t)])}))}),(function(){return function(){for(var t=[],u=arguments.length;u--;)t[u]=arguments[u];return un(t,o.params,!0).then((function(t){return qn(e,r,n,t)})).catch(gr)}}))},Cn=function(t,e,r,n,o){return[Sn(t,"myNamespace",r),e,r,n,o]},Rn=function(t,e,r,n,o){return[wn(t,"onResult",(function(t){mn(t)&&e.$on(_n(r,n,"onResult"),(function(o){Pn(o,t,(function(t){e.$trigger(_n(r,n,"onError"),t)}))}))})),e,r,n,o]},Mn=function(t,e,r,n,o){return[wn(t,"onMessage",(function(t){if(mn(t)){e.$only(_n(r,n,"onMessage"),(function(o){Pn(o,t,(function(t){e.$trigger(_n(r,n,"onError"),t)}))}))}})),e,r,n,o]},Fn=function(t,e,r,n,o){return[wn(t,"onError",(function(t){mn(t)&&e.$only(_n(r,n,"onError"),t)})),e,r,n,o]};function Ln(t,e,r,n,o){var u=[Cn];u.push(Rn,Mn,Fn),u.push(xn);var i=Reflect.apply(jn,null,u);return Reflect.apply(i,null,[n,o,t,e,r])}function Wn(t,e,r,n){return function(){for(var o=[],u=arguments.length;u--;)o[u]=arguments[u];return un(o,n.params,!0).then((function(n){return qn(t,e,r,n)})).catch(gr)}}function Jn(t,e,r){var n={};for(var o in r){var u=r[o];for(var i in u){var a=u[i];n=Sn(n,i,Ln(o,i,a,Wn(e,o,i,a),e))}}return[n,t,e,r]}function In(t,e,r,n){return[wn(t,"onError",(function(t){if(mn(t))for(var e in n)r.$on(_n(e,"onError"),t)})),e,r]}function Dn(t,e,r){return[wn(t,"onReady",(function(t){mn(t)&&r.$on("onReady",t)})),e,r]}var Un=["roundtip","handshake"],Vn={loginHandlerName:an("login",["string"]),logoutHandlerName:an("logout",["string"]),loginMethod:an("handshake",["string"],(zn={},zn.enumv=Un,zn)),useJwt:an(!0,["boolean","string"]),authStrKey:an(null,["string"]),hostname:an(!1,["string"]),namespace:an("jsonql",["string"]),wsOptions:an({},["object"]),contract:an({},["object"],(Nn={},Nn.checker=function(t){return!!function(t){return et(t)&&(bn(t,"query")||bn(t,"mutation")||bn(t,"socket"))}(t)&&t},Nn)),enableAuth:an(!1,["boolean"]),token:an(!1,["string"])},Bn={eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:""};function Hn(t){return Promise.resolve(t).then((function(t){var e;return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new pr(t)}}()),t.wssPath=(e=[t.hostname,t.namespace].join("/"),"ws"===t.serverType?e.replace("http://","ws://"):e),t}))}function Yn(t,e,r){return function(t,e,r){var n=Object.assign(Bn,r),o=Object.assign(Vn,e);return cn(t,o,n)}(t,e,r).then(Hn)}function Gn(t,e){return Promise.resolve(e).then(sn).then((function(t){return{opts:t,nspMap:kn(t),ee:dn(t)}})).then((function(e){var r=e.opts,n=e.nspMap,o=e.ee;return t(r,n,o)})).then((function(t){return function(t,e,r){var n=e.nspSet,o=[Jn,In,Dn];return t.enableAuth?o.push(An):o.push((function(t){return t})),Reflect.apply(jn,null,o)(t,r,n)}(t.opts,t.nspMap,t.ee)})).catch((function(t){console.error("jsonql-ws-core-client init error",t)}))}var Kn=null;"undefined"!=typeof WebSocket?Kn=WebSocket:"undefined"!=typeof MozWebSocket?Kn=MozWebSocket:void 0!==t?Kn=t.WebSocket||t.MozWebSocket:"undefined"!=typeof window?Kn=window.WebSocket||window.MozWebSocket:"undefined"!=typeof self&&(Kn=self.WebSocket||self.MozWebSocket);var Qn=Kn,Xn=function(t){var e=t.toLowerCase();return e.indexOf("http")>-1?e.indexOf("https")>-1?e.replace("https","wss"):e.replace("http","ws"):e};function Zn(t,e){return void 0===e&&(e=!1),!1===e?function(e){return new t(Xn(e))}:function(e,r){var n=Xn(e),o=r&&"string"==typeof r?n+"?token="+r:n;try{return new t(o)}catch(t){return console.error("WebSocket Connection Error",t),!1}}}var to=Array.isArray,eo="object"==typeof t&&t&&t.Object===Object&&t,ro="object"==typeof self&&self&&self.Object===Object&&self,no=(eo||ro||Function("return this")()).Symbol,oo=Object.prototype,uo=oo.hasOwnProperty,io=oo.toString,ao=no?no.toStringTag:void 0;var co=Object.prototype.toString;var fo=no?no.toStringTag:void 0;function so(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":fo&&fo in Object(t)?function(t){var e=uo.call(t,ao),r=t[ao];try{t[ao]=void 0;var n=!0}catch(t){}var o=io.call(t);return n&&(e?t[ao]=r:delete t[ao]),o}(t):function(t){return co.call(t)}(t)}function lo(t){return null!=t&&"object"==typeof t}var po=no?no.prototype:void 0,ho=po?po.toString:void 0;function vo(t){if("string"==typeof t)return t;if(to(t))return function(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var u=Array(o);++n-1;);return r}(o,u),function(t,e){for(var r=t.length;r--&&bo(e,t[r],0)>-1;);return r}(o,u)+1).join("")}var No=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return t.join("_")},xo=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(e,r),e}(Error),Co=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0},statusCode:{configurable:!0}};return r.name.get=function(){return"JsonqlError"},r.statusCode.get=function(){return-1},Object.defineProperties(e,r),e}(Error);var Ro=function(t){void 0===t&&(t=!1);var e=Date.now();return t?Math.floor(e/1e3):e};function Mo(t){return"string"==typeof t||!to(t)&&lo(t)&&"[object String]"==so(t)}function Fo(t,e,r){if(void 0===e&&(e=[]),void 0===r&&(r=!1),Mo(t)&&to(e)){var n=function(t){var e;return(e={}).args=t,e}(e);return!0===r?n:function(t,e){var r;return(r={})[t]=e,r.TS=[Ro()],r}(t,n)}throw new xo("[createQuery] expect resolverName to be string and args to be array!",{resolverName:t,args:e})}function Lo(t,e){var r=e.hostname,n=e.wssPath,o=e.wsOptions;return(0,e.nspClient)(t?[r,t].join("/"):n,o)}var Wo=function(t){return""!==zo(t)&&Mo(t)},Jo=function(){this.__suspend__=null,this.queueStore=new Set},Io={$suspend:{configurable:!0},$queues:{configurable:!0}};Io.$suspend.set=function(t){var e=this;if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value!");var r=this.__suspend__;this.__suspend__=t,this.logger("($suspend)","Change from "+r+" --\x3e "+t),!0===r&&!1===t&&setTimeout((function(){e.release()}),1)},Jo.prototype.$queue=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return!0===this.__suspend__&&(this.logger("($queue)","added to $queue",t),this.queueStore.add(t)),this.__suspend__},Io.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},Jo.prototype.release=function(){var t=this,e=this.queueStore.size;if(this.logger("(release)","Release was called "+e),e>0){var r=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",r),r.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(Jo.prototype,Io);var Do=function(t,e){var r;(to(r=e)?r:[r]).forEach((function(e){t.$off(No(e,"emit"))}))};var Uo=function(t,e,r){var n=r.useCallbackStyle,o=r.log,u=n?"error":"onError",i=n?"result":"onResult";e.$only(No(t,"emit"),(function(r,n){o("[notLoginHandler] hijack the ws call",t,r,n);var a={message:"NOT LOGIN"};e.$call(No(t,r,u),[a]),e.$call(No(t,r,i),[{error:a}])}))};function Vo(t,e,r,n,o,u){var i=function(t){return t.length>1&&t[0]}(o),a=!1,c=t.log;o.forEach((function(o){if(a=i===o,u[o]){c("[call bindWsHandler]",a,o);var f=[o,u[o],r,a,t];if("socket.io"===t.serverType){var s=e.nspSet;f.push(s[o])}Reflect.apply(n,null,f)}else Uo(o,r,t)})),r.$on("__logout__",(function(){c("LOGOUT_EVENT_NAME"),function(t,e,r,n){void 0===n&&(n={});var o=n.useCallbackStyle?"error":"onError";e.forEach((function(e){t.$call(No(e,o),[{message:r,namespace:e}])}))}(r,o,"__logout__"),o.forEach((function(e){Do(r,e),u[e]=!1,Uo(e,r,t)}))}))}var Bo=["__reply__","__event__","__data__"],Ho=function(t){var e=t.data;return!!e&&(Bo.filter((function(t){return function(t,e){try{var r=Object.keys(t);return n=e,!!r.filter((function(t){return t===n})).length}catch(t){return!1}var n}(e,t)})).length===Bo.length&&e)},Yo=function(t,e,r,n,o){var u=[e];r&&u.push(r),u.push(o);var i=Reflect.apply(No,null,u),a=n.data||n;t.$trigger(i,[a])};function Go(t,e,r,n,o){var u=o.useCallbackStyle,i=o.log;i("wsMainHandler log test");var a=u?"ready":"onReady",c=u?"login":"onLogin",f=u?"message":"onMessage",s=u?"result":"onResult",l=u?"error":"onError";e.onopen=function(){i("ws.onopen listened"),r.$call(a,t),n&&(i("isPrivate and fire the "+c),r.$call(c,t)),r.$only(No(t,"emit"),(function(t,r){i("calling server",t,r),e.send(function(t,e,r){return void 0===e&&(e=[]),void 0===r&&(r=!1),JSON.stringify(Fo(t,e,r))}(t,r))}))},e.onmessage=function(e){try{var n=function(t){var e,r=t.data,n=Wo(r)?JSON.parse(r):r;if(!1!==(e=Ho(n)))return{resolverName:e.__event__,data:e.__data__,type:e.__reply__};throw new Co("payload can not be decoded",t)}(e),o=n.resolverName,u=n.type;switch(i("Hear from server",u,n),u){case"emit":var a=No(t,o,f),c=r.$trigger(a,[n]);i("EMIT_REPLY_TYPE",a,c);break;case"acknowledge":var p=No(t,o,s);r.$trigger(p,[n]);break;case"error":i("ERROR_TYPE"),Yo(r,t,o,n,l);break;default:i("Unhandled event!",n),Yo(r,t,o,n,l)}}catch(e){console.error("ws.onmessage error",e),Yo(r,t,!1,e,l)}},e.onclose=function(){i("ws.onclose callback")},r.$on("__logout__",(function(){try{i("terminate ws connection"),e.terminate()}catch(t){console.error("ws.terminate error",t)}}))}var Ko=function(t,e,r){var n,o=e.nspSet,u=e.publicNamespace,i=!1,a=[],c={};if(t.enableAuth)i=!0,c=(a=function(t,e){var r=[];for(var n in t)n===e?r[1]=n:r[0]=n;return r}(o,u)).map((function(e,n){var o,u,i;return 0===n?r?(t.token=r,(o={})[e]=function(t,e){var r=e.hostname,n=e.wssPath,o=e.token,u=e.wsOptions,i=e.nspAuthClient,a=t?[r,t].join("/"):n;if(o&&"string"!=typeof o)throw new Error("Expect token to be string, but got "+o);return i(a,o,u)}(e,t),o):((u={})[e]=!1,u):((i={})[e]=Lo(e,t),i)})).reduce((function(t,e){return Object.assign(t,e)}),{});else{var f=(n=o,Object.keys(n)[0]);a.push(f),c[f]=Lo(!1,t)}return{nsps:c,namespaces:a,login:i}};var Qo=function(t){var e=Zn(t),r=Zn(t,!0);return function(t,n,o){t.nspClient=e,t.nspAuthClient=r;var u=t.log;return u&&"function"==typeof u&&(u("@jsonql/ws ee",o.name),u("@jsonql/ws createClientResolver",t)),function(t,e,r){var n=[t,e,r,Go],o=t.token,u=t.log,i=Ko(t,e,o),a=i.nsps,c=i.namespaces,f=i.login;return Reflect.apply(Vo,null,n.concat([c,a])),f&&r.$only("__login__",(function(o){u("createClient LOGIN_EVENT_NAME"),Do(r,c);var i=Ko(t,e,o);Reflect.apply(Vo,null,n.concat([i.namespaces,i.nsps]))})),{opts:t,nspMap:e,ee:r}}(t,n,o)}}(Qn),Xo={version:"version: 1.1.0 module: umd",serverType:"ws"},Zo={};return function(t,e){return void 0===t&&(t={}),void 0===e&&(e={}),function(t,e,r){return void 0===e&&(e={}),void 0===r&&(r={}),function(n){return void 0===n&&(n={}),Yn(n,e,r).then((function(e){return Gn(t,e)}))}}(Qo,Zo,Object.assign(Xo,e))(t)}})); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).jsonqlWsClient=e()}(this,(function(){"use strict";var t="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},e="object"==typeof t&&t&&t.Object===Object&&t,r="object"==typeof self&&self&&self.Object===Object&&self,n=e||r||Function("return this")(),o=n.Symbol;function u(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var u=Array(o);++n-1;);return r}(n,o),function(t,e){for(var r=t.length;r--&&j(e,t[r],0)>-1;);return r}(n,o)+1).join("")}var M=function(t){return!!i(t)||null!=t&&""!==R(t)};function F(t){return function(t){return"number"==typeof t||v(t)&&"[object Number]"==h(t)}(t)&&t!=+t}function L(t){return"string"==typeof t||!i(t)&&v(t)&&"[object String]"==h(t)}var W=function(t){return!L(t)&&!F(parseFloat(t))},J=function(t){return""!==R(t)&&L(t)},I=function(t){return null!=t&&"boolean"==typeof t},D=function(t,e){return void 0===e&&(e=!0),void 0!==t&&""!==t&&""!==R(t)&&(!1===e||!0===e&&null!==t)},U=function(t){switch(t){case"number":return W;case"string":return J;case"boolean":return I;default:return D}},V=function(t,e){return void 0===e&&(e=""),!!i(t)&&(""===e||""===R(e)||!(t.filter((function(t){return!U(e)(t)})).length>0))},B=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var e=t.replace("array.<","").replace(">","");return e.indexOf("|")?e.split("|"):[e]}return!1},H=function(t,e){var r=t.arg;return e.length>1?!r.filter((function(t){return!(e.length>e.filter((function(e){return!U(e)(t)})).length)})).length:e.length>e.filter((function(t){return!V(r,t)})).length};function Y(t,e){return function(r){return t(e(r))}}var G=Y(Object.getPrototypeOf,Object),K=Function.prototype,Q=Object.prototype,X=K.toString,Z=Q.hasOwnProperty,tt=X.call(Object);function et(t){if(!v(t)||"[object Object]"!=h(t))return!1;var e=G(t);if(null===e)return!0;var r=Z.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&X.call(r)==tt}var rt,nt=function(t,e,r){for(var n=-1,o=Object(t),u=r(t),i=u.length;i--;){var a=u[rt?i:++n];if(!1===e(o[a],a,o))break}return t};function ot(t){return v(t)&&"[object Arguments]"==h(t)}var ut=Object.prototype,it=ut.hasOwnProperty,at=ut.propertyIsEnumerable,ct=ot(function(){return arguments}())?ot:function(t){return v(t)&&it.call(t,"callee")&&!at.call(t,"callee")};var ft="object"==typeof exports&&exports&&!exports.nodeType&&exports,st=ft&&"object"==typeof module&&module&&!module.nodeType&&module,lt=st&&st.exports===ft?n.Buffer:void 0,pt=(lt?lt.isBuffer:void 0)||function(){return!1},ht=/^(?:0|[1-9]\d*)$/;function vt(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&ht.test(t))&&t>-1&&t%1==0&&t-1&&t%1==0&&t<=9007199254740991}var dt={};dt["[object Float32Array]"]=dt["[object Float64Array]"]=dt["[object Int8Array]"]=dt["[object Int16Array]"]=dt["[object Int32Array]"]=dt["[object Uint8Array]"]=dt["[object Uint8ClampedArray]"]=dt["[object Uint16Array]"]=dt["[object Uint32Array]"]=!0,dt["[object Arguments]"]=dt["[object Array]"]=dt["[object ArrayBuffer]"]=dt["[object Boolean]"]=dt["[object DataView]"]=dt["[object Date]"]=dt["[object Error]"]=dt["[object Function]"]=dt["[object Map]"]=dt["[object Number]"]=dt["[object Object]"]=dt["[object RegExp]"]=dt["[object Set]"]=dt["[object String]"]=dt["[object WeakMap]"]=!1;var yt,bt="object"==typeof exports&&exports&&!exports.nodeType&&exports,_t=bt&&"object"==typeof module&&module&&!module.nodeType&&module,mt=_t&&_t.exports===bt&&e.process,jt=function(){try{var t=_t&&_t.require&&_t.require("util").types;return t||mt&&mt.binding&&mt.binding("util")}catch(t){}}(),wt=jt&&jt.isTypedArray,St=wt?(yt=wt,function(t){return yt(t)}):function(t){return v(t)&>(t.length)&&!!dt[h(t)]},Ot=Object.prototype.hasOwnProperty;function kt(t,e){var r=i(t),n=!r&&ct(t),o=!r&&!n&&pt(t),u=!r&&!n&&!o&&St(t),a=r||n||o||u,c=a?function(t,e){for(var r=-1,n=Array(t);++r-1},Ft.prototype.set=function(t,e){var r=this.__data__,n=Rt(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};var Lt,Wt=n["__core-js_shared__"],Jt=(Lt=/[^.]+$/.exec(Wt&&Wt.keys&&Wt.keys.IE_PROTO||""))?"Symbol(src)_1."+Lt:"";var It=Function.prototype.toString;function Dt(t){if(null!=t){try{return It.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var Ut=/^\[object .+?Constructor\]$/,Vt=Function.prototype,Bt=Object.prototype,Ht=Vt.toString,Yt=Bt.hasOwnProperty,Gt=RegExp("^"+Ht.call(Yt).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function Kt(t){return!(!Pt(t)||function(t){return!!Jt&&Jt in t}(t))&&(qt(t)?Gt:Ut).test(Dt(t))}function Qt(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return Kt(r)?r:void 0}var Xt=Qt(n,"Map"),Zt=Qt(Object,"create");var te=Object.prototype.hasOwnProperty;var ee=Object.prototype.hasOwnProperty;function re(t){var e=-1,r=null==t?0:t.length;for(this.clear();++ea))return!1;var f=u.get(t);if(f&&u.get(e))return f==e;var s=-1,l=!0,p=2&r?new ie:void 0;for(u.set(t,e),u.set(e,t);++se.type.filter((function(t){var e;return void 0===r||(!1!==(e=B(t))?!H({arg:r},e):!U(t)(r))})).length)})).length}return!1},rr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 406},r.name.get=function(){return"Jsonql406Error"},Object.defineProperties(e,r),e}(Error),nr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"Jsonql500Error"},Object.defineProperties(e,r),e}(Error),or=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 403},r.name.get=function(){return"JsonqlForbiddenError"},Object.defineProperties(e,r),e}(Error),ur=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlAuthorisationError"},Object.defineProperties(e,r),e}(Error),ir=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlContractAuthError"},Object.defineProperties(e,r),e}(Error),ar=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"JsonqlResolverAppError"},Object.defineProperties(e,r),e}(Error),cr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 404},r.name.get=function(){return"JsonqlResolverNotFoundError"},Object.defineProperties(e,r),e}(Error),fr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlEnumError"},Object.defineProperties(e,r),e}(Error),sr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlTypeError"},Object.defineProperties(e,r),e}(Error),lr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlCheckerError"},Object.defineProperties(e,r),e}(Error),pr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(e,r),e}(Error),hr=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0},statusCode:{configurable:!0}};return r.name.get=function(){return"JsonqlError"},r.statusCode.get=function(){return-1},Object.defineProperties(e,r),e}(Error),vr=function(t){function e(r,n){t.call(this,n),this.statusCode=r,this.className=e.name}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlServerError"},Object.defineProperties(e,r),e}(Error);function gr(t){if(Array.isArray(t))throw new pr("",t);var e=t.message||"No message",r=t.detail||t;switch(!0){case t instanceof rr:throw new rr(e,r);case t instanceof nr:throw new nr(e,r);case t instanceof or:throw new or(e,r);case t instanceof ur:throw new ur(e,r);case t instanceof ir:throw new ir(e,r);case t instanceof ar:throw new ar(e,r);case t instanceof cr:throw new cr(e,r);case t instanceof fr:throw new fr(e,r);case t instanceof sr:throw new sr(e,r);case t instanceof lr:throw new lr(e,r);case t instanceof pr:throw new pr(e,r);case t instanceof vr:throw new vr(e,r);default:throw new hr(e,r)}}var dr=function(t,e){var r,n,o,u,i;switch(!0){case"object"===t:return o=(n=e).arg,u=n.param,i=[o],Array.isArray(u.keys)&&u.keys.length&&i.push(u.keys),!Reflect.apply(er,null,i);case"array"===t:return!V(e.arg);case!1!==(r=B(t)):return!H(e,r);default:return!U(t)(e.arg)}},yr=function(t,e){return void 0!==t?t:!0===e.optional&&void 0!==e.defaultvalue?e.defaultvalue:null},br=function(t,e,r){var n;void 0===r&&(r=!1);var o=function(t,e){if(!V(e))throw new hr("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===e.length)return[];if(!V(t))throw new hr("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==e.length:return t.map((function(t,r){return{arg:t,index:r,param:e[r]}}));case!0===e[0].variable:var r=e[0].type;return t.map((function(t,n){return{arg:t,index:n,param:e[n]||{type:r,name:"_"}}}));case t.lengthe.length:var n=e.length,o=["any"];return t.map((function(t,r){var u=r>=n||!!e[r].optional,i=e[r]||{type:o,name:"_"+r};return{arg:u?yr(t,i):t,index:r,param:i,optional:u}}));default:throw new hr("Could not understand your arguments and parameter structure!",{args:t,params:e})}}(t,e),u=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var e=t.arg,r=t.param;return!!M(e)&&!(r.type.length>r.type.filter((function(e){return dr(e,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(e){return dr(e,t)})).length)}));return r?((n={}).error=u,n.data=o.map((function(t){return t.arg})),n):u},_r=function(){try{var t=Qt(Object,"defineProperty");return t({},"",{}),t}catch(t){}}();function mr(t,e,r){"__proto__"==e&&_r?_r(t,e,{configurable:!0,enumerable:!0,value:r,writable:!0}):t[e]=r}function jr(t,e,r){(void 0===r||Ct(t[e],r))&&(void 0!==r||e in t)||mr(t,e,r)}var wr="object"==typeof exports&&exports&&!exports.nodeType&&exports,Sr=wr&&"object"==typeof module&&module&&!module.nodeType&&module,Or=Sr&&Sr.exports===wr?n.Buffer:void 0,kr=Or?Or.allocUnsafe:void 0;function Er(t,e){var r,n,o=e?(r=t.buffer,n=new r.constructor(r.byteLength),new fe(n).set(new fe(r)),n):t.buffer;return new t.constructor(o,t.byteOffset,t.length)}var $r=Object.create,Tr=function(){function t(){}return function(e){if(!Pt(e))return{};if($r)return $r(e);t.prototype=e;var r=new t;return t.prototype=void 0,r}}();function Ar(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var Pr=Object.prototype.hasOwnProperty;function qr(t,e,r){var n=t[e];Pr.call(t,e)&&Ct(n,r)&&(void 0!==r||e in t)||mr(t,e,r)}var zr=Object.prototype.hasOwnProperty;function Nr(t){if(!Pt(t))return function(t){var e=[];if(null!=t)for(var r in Object(t))e.push(r);return e}(t);var e=$t(t),r=[];for(var n in t)("constructor"!=n||!e&&zr.call(t,n))&&r.push(n);return r}function xr(t){return zt(t)?kt(t,!0):Nr(t)}function Cr(t){return function(t,e,r,n){var o=!r;r||(r={});for(var u=-1,i=e.length;++u0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}(Wr);function Dr(t,e){return Ir(function(t,e,r){return e=Lr(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,u=Lr(n.length-e,0),i=Array(u);++o1?e[n-1]:void 0,u=n>2?e[2]:void 0;for(o=Ur.length>3&&"function"==typeof o?(n--,o):void 0,u&&function(t,e,r){if(!Pt(r))return!1;var n=typeof e;return!!("number"==n?zt(r)&&vt(e,r.length):"string"==n&&e in r)&&Ct(r[e],t)}(e[0],e[1],u)&&(o=n<3?void 0:o,n=1),t=Object(t);++r0?Array.from(this.queueStore):[]},hn.prototype.release=function(){var t=this,e=this.queueStore.size;if(this.logger("(release)","Release was called "+e),e>0){var r=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",r),r.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(hn.prototype,vn);var gn=function(t){function e(e){if("function"!=typeof e)throw new Error("Just die here the logger is not a function!");t.call(this,{logger:e})}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(e.prototype,r),e}(function(t){function e(e){void 0===e&&(e={}),t.call(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={$done:{configurable:!0}};return e.prototype.logger=function(){},e.prototype.$on=function(t,e,r){var n=this;void 0===r&&(r=null);this.validate(t,e);var o=this.takeFromStore(t);if(!1===o)return this.logger("($on)",t+" callback is not in lazy store"),this.addToNormalStore(t,"on",e,r);this.logger("($on)",t+" found in lazy store");var u=0;return o.forEach((function(o){var i=o[0],a=o[1],c=o[2];if(c&&"on"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);n.logger("($on)","call run on "+t),n.run(e,i,r||a),u+=n.addToNormalStore(t,"on",e,r||a)})),u},e.prototype.$once=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=this.takeFromStore(t);this.normalStore;if(!1===n)return this.logger("($once)",t+" not in the lazy store"),this.addToNormalStore(t,"once",e,r);this.logger("($once)",n);var o=Array.from(n)[0],u=o[0],i=o[1],a=o[2];if(a&&"once"!==a)throw new Error("You are trying to register an event already been taken by other type: "+a);this.logger("($once)","call run for "+t),this.run(e,u,r||i),this.$off(t)},e.prototype.$only=function(t,e,r){var n=this;void 0===r&&(r=null),this.validate(t,e);var o=!1,u=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger("($only)",t+" add to store"),o=this.addToNormalStore(t,"only",e,r)),!1!==u)&&(this.logger("($only)",t+" found data in lazy store to execute"),Array.from(u).forEach((function(o){var u=o[0],i=o[1],a=o[2];if(a&&"only"!==a)throw new Error("You are trying to register an event already been taken by other type: "+a);n.logger("($only)","call run for "+t),n.run(e,u,r||i)})));return o},e.prototype.$onlyOnce=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=!1,o=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger("($onlyOnce)",t+" add to store"),n=this.addToNormalStore(t,"onlyOnce",e,r)),!1!==o){this.logger("($onlyOnce)",o);var u=Array.from(o)[0],i=u[0],a=u[1],c=u[2];if(c&&"onlyOnce"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);this.logger("($onlyOnce)","call run for "+t),this.run(e,i,r||a),this.$off(t)}return n},e.prototype.$replace=function(t,e,r,n){if(void 0===r&&(r=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,e),Reflect.apply(o,this,[t,e,r])}throw new Error(n+" is not supported!")},e.prototype.$trigger=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,u=this.normalStore;if(this.logger("($trigger)","normalStore",u),u.has(t)){var i=this.$queue(t,e,r,n);if(this.logger("($trigger)",t,"found; add to queue: ",i),!0===i)return this.logger("($trigger)",t,"not executed. Exit now."),!1;for(var a=Array.from(u.get(t)),c=a.length,f=!1,s=0;s0;)n[o]=arguments[o+2];if(t.has(e)?(this.logger("(addToStore)",e+" existed"),r=t.get(e)):(this.logger("(addToStore)","create new Set for "+e),r=new Set),n.length>2)if(Array.isArray(n[0])){var u=n[2];this.checkTypeInLazyStore(e,u)||r.add(n)}else this.checkContentExist(n,r)||(this.logger("(addToStore)","insert new",n),r.add(n));else r.add(n);return t.set(e,r),[t,r.size]},e.prototype.checkContentExist=function(t,e){return!!Array.from(e).filter((function(e){return e[0]===t[0]})).length},e.prototype.checkTypeInStore=function(t,e){this.validateEvt(t,e);var r=this.$get(t,!0);return!1===r||!r.filter((function(t){var r=t[3];return e!==r})).length},e.prototype.checkTypeInLazyStore=function(t,e){this.validateEvt(t,e);var r=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",r),!!r&&!!Array.from(r).filter((function(t){return t[2]!==e})).length},e.prototype.addToNormalStore=function(t,e,r,n){if(void 0===n&&(n=null),this.logger("(addToNormalStore)",t,e,"try to add to normal store"),this.checkTypeInStore(t,e)){this.logger("(addToNormalStore)",e+" can add to "+t+" normal store");var o=this.hashFnToKey(r),u=[this.normalStore,t,o,r,n,e],i=Reflect.apply(this.addToStore,this,u),a=i[0],c=i[1];return this.normalStore=a,c}return!1},e.prototype.addToLazyStore=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(e),r];n&&o.push(n);var u=Reflect.apply(this.addToStore,this,o),i=u[0],a=u[1];return this.lazyStore=i,a},e.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},r.normalStore.set=function(t){ln.set(this,t)},r.normalStore.get=function(){return ln.get(this)},r.lazyStore.set=function(t){pn.set(this,t)},r.lazyStore.get=function(){return pn.get(this)},e.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,e){return(t=(t<<5)-t+e.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(e.prototype,r),e}(hn))),dn=function(t){var e=t.log,r=t.eventEmitter;return r?(e("eventEmitter is:",r.name),r):(e("Create a new Event Emitter"),new gn(t.log))},yn=function(t){return i(t)?t:[t]},bn=function(t,e){try{var r=Object.keys(t);return n=e,!!r.filter((function(t){return t===n})).length}catch(t){return!1}var n},_n=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return t.join("_")},mn=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},jn=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return Reflect.apply(e,null,yn(t))}),Reflect.apply(t,null,r))}};function wn(t,e,r,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,e)&&Object.defineProperty(t,e,{set:r,get:null===n?function(){return null}:n}),t}function Sn(t,e,r,n){void 0===n&&(n=!1);var o=function(t,e){var r=Object.getOwnPropertyDescriptor(t,e);return void 0!==r&&r.value?r.value:r}(t,e);return!1===n&&void 0!==o||Object.defineProperty(t,e,{value:r,writable:n}),t}function On(t){return!!bn(t,"socket")&&t.socket}function kn(t){var e,r,n=t.contract;return t.enableAuth?function(t,e){void 0===e&&(e=!1);var r=On(t);if(!1===r){if(e)return t;throw new hr("socket not found in contract!")}var n,o={},u=0;for(var i in r){var a=r[i],c=a.namespace;c&&(o[c]||(++u,o[c]={}),o[c][i]=a,n||a.public&&(n=c))}return{size:u,nspSet:o,publicNamespace:n}}(n):((r={}).nspSet=((e={}).jsonql=function(t){var e=On(t);if(!1!==e)return e;throw new cr("Missing property in contract!")}(n),e),r.publicNamespace="jsonql",r)}var En=function(t,e,r){return[Sn(t,e.loginHandlerName,(function(t){if(t&&on(t))return r.$trigger("__login__",[t]);throw new pr(e.loginHandlerName,"Unexpected token "+t)})),r,e]},$n=function(t,e,r){return[Sn(t,e.logoutHandlerName,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__logout__",t)})),r]};function Tn(t,e){return objDefineProps(t,"onLogin",(function(t){isFunc(t)&&e.$only("onLogin",t)}))}function An(t,e,r){return jn(En,$n,Tn)(t,e,r)}function Pn(t,e,r){bn(t,"error")?r(t.error):bn(t,"data")?e(t.data):r({message:"UKNNOWN RESULT!",error:t})}function qn(t,e,r,n){void 0===n&&(n=[]);var o=_n(e,"emit");return debugFn("actionCall: "+o+" --\x3e "+r,n),t.$trigger(o,[r,yn(n)]),new Promise((function(n,o){t.$on(_n(e,r,"onResult"),(function(t){debugFn("got the first result",t),Pn(t,n,o)}))}))}var zn,Nn,xn=function(t,e,r,n,o){return wn(t,"send",(function(t){un(yn(t),o.params,!0).then((function(o){if(!o.error||!o.error.length)return qn(e,r,n,t);e.$call(_n(r,n,"onError"),[new pr(n,o.error)])})).catch((function(t){e.$call(_n(r,n,"onError"),[new pr(n,t)])}))}),(function(){return function(){for(var t=[],u=arguments.length;u--;)t[u]=arguments[u];return un(t,o.params,!0).then((function(t){return qn(e,r,n,t)})).catch(gr)}}))},Cn=function(t,e,r,n,o){return[Sn(t,"myNamespace",r),e,r,n,o]},Rn=function(t,e,r,n,o){return[wn(t,"onResult",(function(t){mn(t)&&e.$on(_n(r,n,"onResult"),(function(o){Pn(o,t,(function(t){e.$trigger(_n(r,n,"onError"),t)}))}))})),e,r,n,o]},Mn=function(t,e,r,n,o){return[wn(t,"onMessage",(function(t){if(mn(t)){e.$only(_n(r,n,"onMessage"),(function(o){Pn(o,t,(function(t){e.$trigger(_n(r,n,"onError"),t)}))}))}})),e,r,n,o]},Fn=function(t,e,r,n,o){return[wn(t,"onError",(function(t){mn(t)&&e.$only(_n(r,n,"onError"),t)})),e,r,n,o]};function Ln(t,e,r,n,o){var u=[Cn];u.push(Rn,Mn,Fn),u.push(xn);var i=Reflect.apply(jn,null,u);return Reflect.apply(i,null,[n,o,t,e,r])}function Wn(t,e,r,n){return function(){for(var o=[],u=arguments.length;u--;)o[u]=arguments[u];return un(o,n.params,!0).then((function(n){return qn(t,e,r,n)})).catch(gr)}}function Jn(t,e,r){var n={};for(var o in r){var u=r[o];for(var i in u){var a=u[i];n=Sn(n,i,Ln(o,i,a,Wn(e,o,i,a),e))}}return[n,t,e,r]}function In(t,e,r,n){return[wn(t,"onError",(function(t){if(mn(t))for(var e in n)r.$on(_n(e,"onError"),t)})),e,r]}function Dn(t,e,r){return[wn(t,"onReady",(function(t){mn(t)&&r.$on("onReady",t)})),e,r]}var Un=["roundtip","handshake"],Vn={loginHandlerName:an("login",["string"]),logoutHandlerName:an("logout",["string"]),loginMethod:an("handshake",["string"],(zn={},zn.enumv=Un,zn)),useJwt:an(!0,["boolean","string"]),authStrKey:an(null,["string"]),hostname:an(!1,["string"]),namespace:an("jsonql",["string"]),wsOptions:an({},["object"]),contract:an({},["object"],(Nn={},Nn.checker=function(t){return!!function(t){return et(t)&&(bn(t,"query")||bn(t,"mutation")||bn(t,"socket"))}(t)&&t},Nn)),enableAuth:an(!1,["boolean"]),token:an(!1,["string"])},Bn={eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:""};function Hn(t){return Promise.resolve(t).then((function(t){var e;return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new pr(t)}}()),t.wssPath=(e=[t.hostname,t.namespace].join("/"),"ws"===t.serverType?e.replace("http://","ws://"):e),t}))}function Yn(t,e,r){return function(t,e,r){var n=Object.assign(Bn,r),o=Object.assign(Vn,e);return cn(t,o,n)}(t,e,r).then(Hn)}function Gn(t,e){return Promise.resolve(e).then(sn).then((function(t){return{opts:t,nspMap:kn(t),ee:dn(t)}})).then((function(e){var r=e.opts,n=e.nspMap,o=e.ee;return t(r,n,o)})).then((function(t){return function(t,e,r){var n=e.nspSet,o=[Jn,In,Dn];return t.enableAuth?o.push(An):o.push((function(t){return t})),Reflect.apply(jn,null,o)(t,r,n)}(t.opts,t.nspMap,t.ee)})).catch((function(t){console.error("jsonql-ws-core-client init error",t)}))}var Kn=null;"undefined"!=typeof WebSocket?Kn=WebSocket:"undefined"!=typeof MozWebSocket?Kn=MozWebSocket:void 0!==t?Kn=t.WebSocket||t.MozWebSocket:"undefined"!=typeof window?Kn=window.WebSocket||window.MozWebSocket:"undefined"!=typeof self&&(Kn=self.WebSocket||self.MozWebSocket);var Qn=Kn,Xn=function(t){var e=t.toLowerCase();return e.indexOf("http")>-1?e.indexOf("https")>-1?e.replace("https","wss"):e.replace("http","ws"):e};function Zn(t,e){return void 0===e&&(e=!1),!1===e?function(e){return new t(Xn(e))}:function(e,r){var n=Xn(e),o=r&&"string"==typeof r?n+"?token="+r:n;try{return new t(o)}catch(t){return console.error("WebSocket Connection Error",t),!1}}}var to=Array.isArray,eo="object"==typeof t&&t&&t.Object===Object&&t,ro="object"==typeof self&&self&&self.Object===Object&&self,no=(eo||ro||Function("return this")()).Symbol,oo=Object.prototype,uo=oo.hasOwnProperty,io=oo.toString,ao=no?no.toStringTag:void 0;var co=Object.prototype.toString;var fo=no?no.toStringTag:void 0;function so(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":fo&&fo in Object(t)?function(t){var e=uo.call(t,ao),r=t[ao];try{t[ao]=void 0;var n=!0}catch(t){}var o=io.call(t);return n&&(e?t[ao]=r:delete t[ao]),o}(t):function(t){return co.call(t)}(t)}function lo(t){return null!=t&&"object"==typeof t}var po=no?no.prototype:void 0,ho=po?po.toString:void 0;function vo(t){if("string"==typeof t)return t;if(to(t))return function(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var u=Array(o);++n-1;);return r}(o,u),function(t,e){for(var r=t.length;r--&&bo(e,t[r],0)>-1;);return r}(o,u)+1).join("")}var No=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return t.join("_")},xo=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(e,r),e}(Error),Co=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0},statusCode:{configurable:!0}};return r.name.get=function(){return"JsonqlError"},r.statusCode.get=function(){return-1},Object.defineProperties(e,r),e}(Error);var Ro=function(t){void 0===t&&(t=!1);var e=Date.now();return t?Math.floor(e/1e3):e};function Mo(t){return"string"==typeof t||!to(t)&&lo(t)&&"[object String]"==so(t)}function Fo(t,e,r){if(void 0===e&&(e=[]),void 0===r&&(r=!1),Mo(t)&&to(e)){var n=function(t){var e;return(e={}).args=t,e}(e);return!0===r?n:function(t,e){var r;return(r={})[t]=e,r.TS=[Ro()],r}(t,n)}throw new xo("[createQuery] expect resolverName to be string and args to be array!",{resolverName:t,args:e})}function Lo(t,e){var r=e.hostname,n=e.wssPath,o=e.wsOptions;return(0,e.nspClient)(t?[r,t].join("/"):n,o)}var Wo=function(t){return""!==zo(t)&&Mo(t)},Jo=function(){this.__suspend__=null,this.queueStore=new Set},Io={$suspend:{configurable:!0},$queues:{configurable:!0}};Io.$suspend.set=function(t){var e=this;if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value!");var r=this.__suspend__;this.__suspend__=t,this.logger("($suspend)","Change from "+r+" --\x3e "+t),!0===r&&!1===t&&setTimeout((function(){e.release()}),1)},Jo.prototype.$queue=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return!0===this.__suspend__&&(this.logger("($queue)","added to $queue",t),this.queueStore.add(t)),this.__suspend__},Io.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},Jo.prototype.release=function(){var t=this,e=this.queueStore.size;if(this.logger("(release)","Release was called "+e),e>0){var r=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",r),r.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(Jo.prototype,Io);var Do=function(t,e){var r;(to(r=e)?r:[r]).forEach((function(e){t.$off(No(e,"emit"))}))};var Uo=function(t,e,r){var n=r.useCallbackStyle,o=r.log,u=n?"error":"onError",i=n?"result":"onResult";e.$only(No(t,"emit"),(function(r,n){o("[notLoginHandler] hijack the ws call",t,r,n);var a={message:"NOT LOGIN"};e.$call(No(t,r,u),[a]),e.$call(No(t,r,i),[{error:a}])}))};function Vo(t,e,r,n,o,u){var i=function(t){return t.length>1&&t[0]}(o),a=!1,c=t.log;o.forEach((function(o){if(a=i===o,u[o]){c("[call bindWsHandler]",a,o);var f=[o,u[o],r,a,t];if("socket.io"===t.serverType){var s=e.nspSet;f.push(s[o])}Reflect.apply(n,null,f)}else Uo(o,r,t)})),r.$on("__logout__",(function(){c("LOGOUT_EVENT_NAME"),function(t,e,r,n){void 0===n&&(n={});var o=n.useCallbackStyle?"error":"onError";e.forEach((function(e){t.$call(No(e,o),[{message:r,namespace:e}])}))}(r,o,"__logout__"),o.forEach((function(e){Do(r,e),u[e]=!1,Uo(e,r,t)}))}))}var Bo=["__reply__","__event__","__data__"],Ho=function(t){var e=t.data;return!!e&&(Bo.filter((function(t){return function(t,e){try{var r=Object.keys(t);return n=e,!!r.filter((function(t){return t===n})).length}catch(t){return!1}var n}(e,t)})).length===Bo.length&&e)},Yo=function(t,e,r,n,o){var u=[e];r&&u.push(r),u.push(o);var i=Reflect.apply(No,null,u),a=n.data||n;t.$trigger(i,[a])};function Go(t,e,r,n,o){var u=o.useCallbackStyle,i=o.log;i("wsMainHandler log test");var a=u?"ready":"onReady",c=u?"login":"onLogin",f=u?"message":"onMessage",s=u?"result":"onResult",l=u?"error":"onError";e.onopen=function(){i("ws.onopen listened"),r.$call(a,t),n&&(i("isPrivate and fire the "+c),r.$call(c,t)),r.$only(No(t,"emit"),(function(t,r){i("calling server",t,r),e.send(function(t,e,r){return void 0===e&&(e=[]),void 0===r&&(r=!1),JSON.stringify(Fo(t,e,r))}(t,r))}))},e.onmessage=function(e){try{var n=function(t){var e,r=t.data,n=Wo(r)?JSON.parse(r):r;if(!1!==(e=Ho(n)))return{resolverName:e.__event__,data:e.__data__,type:e.__reply__};throw new Co("payload can not be decoded",t)}(e),o=n.resolverName,u=n.type;switch(i("Hear from server",u,n),u){case"emit":var a=No(t,o,f),c=r.$trigger(a,[n]);i("EMIT_REPLY_TYPE",a,c);break;case"acknowledge":var p=No(t,o,s);r.$trigger(p,[n]);break;case"error":i("ERROR_TYPE"),Yo(r,t,o,n,l);break;default:i("Unhandled event!",n),Yo(r,t,o,n,l)}}catch(e){console.error("ws.onmessage error",e),Yo(r,t,!1,e,l)}},e.onclose=function(){i("ws.onclose callback")},r.$on("__logout__",(function(){try{i("terminate ws connection"),e.terminate()}catch(t){console.error("ws.terminate error",t)}}))}var Ko=function(t,e,r){var n,o=e.nspSet,u=e.publicNamespace,i=!1,a=[],c={};if(t.enableAuth)i=!0,c=(a=function(t,e){var r=[];for(var n in t)n===e?r[1]=n:r[0]=n;return r}(o,u)).map((function(e,n){var o,u,i;return 0===n?r?(t.token=r,(o={})[e]=function(t,e){var r=e.hostname,n=e.wssPath,o=e.token,u=e.wsOptions,i=e.nspAuthClient,a=t?[r,t].join("/"):n;if(o&&"string"!=typeof o)throw new Error("Expect token to be string, but got "+o);return i(a,o,u)}(e,t),o):((u={})[e]=!1,u):((i={})[e]=Lo(e,t),i)})).reduce((function(t,e){return Object.assign(t,e)}),{});else{var f=(n=o,Object.keys(n)[0]);a.push(f),c[f]=Lo(!1,t)}return{nsps:c,namespaces:a,login:i}};var Qo=function(t){var e=Zn(t),r=Zn(t,!0);return function(t,n,o){t.nspClient=e,t.nspAuthClient=r;var u=t.log;return u&&"function"==typeof u&&(u("@jsonql/ws ee",o.name),u("@jsonql/ws createClientResolver",t)),function(t,e,r){var n=[t,e,r,Go],o=t.token,u=t.log,i=Ko(t,e,o),a=i.nsps,c=i.namespaces,f=i.login;return Reflect.apply(Vo,null,n.concat([c,a])),f&&r.$only("__login__",(function(o){u("createClient LOGIN_EVENT_NAME"),Do(r,c);var i=Ko(t,e,o);Reflect.apply(Vo,null,n.concat([i.namespaces,i.nsps]))})),{opts:t,nspMap:e,ee:r}}(t,n,o)}}(Qn),Xo={version:"version: 1.1.0 module: umd",serverType:"ws"},Zo={};return function(t,e){return void 0===t&&(t={}),void 0===e&&(e={}),function(t,e,r){return void 0===e&&(e={}),void 0===r&&(r={}),function(n){return void 0===n&&(n={}),Yn(n,e,r).then((function(e){return Gn(t,e)}))}}(Qo,Object.assign({},Vn,Zo),Object.assign({},Bn,Xo,e))(t)}})); //# sourceMappingURL=jsonql-ws-client.umd.js.map diff --git a/packages/@jsonql/ws/node.js b/packages/@jsonql/ws/node.js new file mode 100644 index 00000000..3d7b40ea --- /dev/null +++ b/packages/@jsonql/ws/node.js @@ -0,0 +1,2 @@ +"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t,e=(t=require("ws"))&&"object"==typeof t&&"default"in t?t.default:t,r=function(t){var e=t.toLowerCase();return e.indexOf("http")>-1?e.indexOf("https")>-1?e.replace("https","wss"):e.replace("http","ws"):e};function n(t,e){return void 0===e&&(e=!1),!1===e?function(e){return new t(r(e))}:function(e,n){var o=r(e),a=n&&"string"==typeof n?o+"?token="+n:o;try{return new t(a)}catch(t){return console.error("WebSocket Connection Error",t),!1}}}var o=Array.isArray,a="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},i="object"==typeof a&&a&&a.Object===Object&&a,u="object"==typeof self&&self&&self.Object===Object&&self,c=(i||u||Function("return this")()).Symbol,s=Object.prototype,l=s.hasOwnProperty,f=s.toString,p=c?c.toStringTag:void 0;var h=Object.prototype.toString;var g=c?c.toStringTag:void 0;function d(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":g&&g in Object(t)?function(t){var e=l.call(t,p),r=t[p];try{t[p]=void 0;var n=!0}catch(t){}var o=f.call(t);return n&&(e?t[p]=r:delete t[p]),o}(t):function(t){return h.call(t)}(t)}var v,y,m=(v=Object.getPrototypeOf,y=Object,function(t){return v(y(t))});function b(t){return null!=t&&"object"==typeof t}var _=Function.prototype,w=Object.prototype,S=_.toString,E=w.hasOwnProperty,k=S.call(Object);function j(t){if(!b(t)||"[object Object]"!=d(t))return!1;var e=m(t);if(null===e)return!0;var r=E.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&S.call(r)==k}var $=c?c.prototype:void 0,O=$?$.toString:void 0;function T(t){if("string"==typeof t)return t;if(o(t))return function(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r=n?t:function(t,e,r){var n=-1,o=t.length;e<0&&(e=-e>o?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var a=Array(o);++n-1;);return r}(o,a),function(t,e){for(var r=t.length;r--&&q(e,t[r],0)>-1;);return r}(o,a)+1).join("")}var K=function(t){return o(t)?t:[t]},D=function(t,e){try{var r=Object.keys(t);return n=e,!!r.filter((function(t){return t===n})).length}catch(t){return!1}var n},G=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return t.join("_")},V=function(t){if("function"==typeof t)return!0;console.error("Expect to be Function type! Got "+typeof t)},B=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return Reflect.apply(e,null,K(t))}),Reflect.apply(t,null,r))}};function Q(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];return e.reduce((function(t,e){return t.then((function(t){return e(t)}))}),Reflect.apply(t,null,r))}}function X(t,e,r,n){return void 0===n&&(n=null),void 0===Object.getOwnPropertyDescriptor(t,e)&&Object.defineProperty(t,e,{set:r,get:null===n?function(){return null}:n}),t}function Z(t,e,r,n){void 0===n&&(n=!1);var o=function(t,e){var r=Object.getOwnPropertyDescriptor(t,e);return void 0!==r&&r.value?r.value:r}(t,e);return!1===n&&void 0!==o||Object.defineProperty(t,e,{value:r,writable:n}),t}var tt=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 406},r.name.get=function(){return"Jsonql406Error"},Object.defineProperties(e,r),e}(Error),et=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"Jsonql500Error"},Object.defineProperties(e,r),e}(Error),rt=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 403},r.name.get=function(){return"JsonqlForbiddenError"},Object.defineProperties(e,r),e}(Error),nt=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlAuthorisationError"},Object.defineProperties(e,r),e}(Error),ot=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 401},r.name.get=function(){return"JsonqlContractAuthError"},Object.defineProperties(e,r),e}(Error),at=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 500},r.name.get=function(){return"JsonqlResolverAppError"},Object.defineProperties(e,r),e}(Error),it=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={statusCode:{configurable:!0},name:{configurable:!0}};return r.statusCode.get=function(){return 404},r.name.get=function(){return"JsonqlResolverNotFoundError"},Object.defineProperties(e,r),e}(Error),ut=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlEnumError"},Object.defineProperties(e,r),e}(Error),ct=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlTypeError"},Object.defineProperties(e,r),e}(Error),st=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlCheckerError"},Object.defineProperties(e,r),e}(Error),lt=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(e,r),e}(Error),ft=function(t){function e(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];t.apply(this,r),this.message=r[0],this.detail=r[1],this.className=e.name,t.captureStackTrace&&t.captureStackTrace(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0},statusCode:{configurable:!0}};return r.name.get=function(){return"JsonqlError"},r.statusCode.get=function(){return-1},Object.defineProperties(e,r),e}(Error),pt=function(t){function e(r,n){t.call(this,n),this.statusCode=r,this.className=e.name}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"JsonqlServerError"},Object.defineProperties(e,r),e}(Error);function ht(t){if(Array.isArray(t))throw new lt("",t);var e=t.message||"No message",r=t.detail||t;switch(!0){case t instanceof tt:throw new tt(e,r);case t instanceof et:throw new et(e,r);case t instanceof rt:throw new rt(e,r);case t instanceof nt:throw new nt(e,r);case t instanceof ot:throw new ot(e,r);case t instanceof at:throw new at(e,r);case t instanceof it:throw new it(e,r);case t instanceof ut:throw new ut(e,r);case t instanceof ct:throw new ct(e,r);case t instanceof st:throw new st(e,r);case t instanceof lt:throw new lt(e,r);case t instanceof pt:throw new pt(e,r);default:throw new ft(e,r)}}function gt(t){return!!D(t,"socket")&&t.socket}var dt=function(t){void 0===t&&(t=!1);var e=Date.now();return t?Math.floor(e/1e3):e};function vt(t){return"string"==typeof t||!o(t)&&b(t)&&"[object String]"==d(t)}function yt(t,e,r){if(void 0===e&&(e=[]),void 0===r&&(r=!1),vt(t)&&o(e)){var n=function(t){var e;return(e={}).args=t,e}(e);return!0===r?n:function(t,e){var r;return(r={})[t]=e,r.TS=[dt()],r}(t,n)}throw new lt("[createQuery] expect resolverName to be string and args to be array!",{resolverName:t,args:e})}function mt(t,e){var r=e.hostname,n=e.wssPath,o=e.wsOptions;return(0,e.nspClient)(t?[r,t].join("/"):n,o)}function bt(t){return function(t){return"number"==typeof t||b(t)&&"[object Number]"==d(t)}(t)&&t!=+t}var _t=function(t){return!vt(t)&&!bt(parseFloat(t))},wt=function(t){return""!==W(t)&&vt(t)},St=function(t){return null!=t&&"boolean"==typeof t},Et=function(t,e){return void 0===e&&(e=!0),void 0!==t&&""!==t&&""!==W(t)&&(!1===e||!0===e&&null!==t)},kt=function(t){switch(t){case"number":return _t;case"string":return wt;case"boolean":return St;default:return Et}},jt=function(t,e){return void 0===e&&(e=""),!!o(t)&&(""===e||""===W(e)||!(t.filter((function(t){return!kt(e)(t)})).length>0))},$t=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var e=t.replace("array.<","").replace(">","");return e.indexOf("|")?e.split("|"):[e]}return!1},Ot=function(t,e){var r=t.arg;return e.length>1?!r.filter((function(t){return!(e.length>e.filter((function(e){return!kt(e)(t)})).length)})).length:e.length>e.filter((function(t){return!jt(r,t)})).length},Tt=function(t,e){if(void 0===e&&(e=null),j(t)){if(!e)return!0;if(jt(e))return!e.filter((function(e){var r=t[e.name];return!(e.type.length>e.type.filter((function(t){var e;return void 0===r||(!1!==(e=$t(t))?!Ot({arg:r},e):!kt(t)(r))})).length)})).length}return!1},Nt=function(t){var e,r=t.arg,n=t.param;return!!(o(e=r)||null!=e&&""!==W(e))&&!(n.type.length>n.type.filter((function(e){return Ct(e,t)})).length)},Ct=function(t,e){var r,n,o,a,i;switch(!0){case"object"===t:return o=(n=e).arg,a=n.param,i=[o],Array.isArray(a.keys)&&a.keys.length&&i.push(a.keys),!Reflect.apply(Tt,null,i);case"array"===t:return!jt(e.arg);case!1!==(r=$t(t)):return!Ot(e,r);default:return!kt(t)(e.arg)}},qt=function(t,e){return void 0!==t?t:!0===e.optional&&void 0!==e.defaultvalue?e.defaultvalue:null},At=function(t,e,r){var n;void 0===r&&(r=!1);var o=function(t,e){if(!jt(e))throw new ft("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===e.length)return[];if(!jt(t))throw new ft("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==e.length:return t.map((function(t,r){return{arg:t,index:r,param:e[r]}}));case!0===e[0].variable:var r=e[0].type;return t.map((function(t,n){return{arg:t,index:n,param:e[n]||{type:r,name:"_"}}}));case t.lengthe.length:var n=e.length,o=["any"];return t.map((function(t,r){var a=r>=n||!!e[r].optional,i=e[r]||{type:o,name:"_"+r};return{arg:a?qt(t,i):t,index:r,param:i,optional:a}}));default:throw new ft("Could not understand your arguments and parameter structure!",{args:t,params:e})}}(t,e),a=o.filter((function(t){return!0===t.optional||!0===t.param.optional?Nt(t):!(t.param.type.length>t.param.type.filter((function(e){return Ct(e,t)})).length)}));return r?((n={}).error=a,n.data=o.map((function(t){return t.arg})),n):a};function Pt(t,e,r,n,o,a){void 0===r&&(r=!1),void 0===n&&(n=!1),void 0===o&&(o=!1),void 0===a&&(a=!1);var i={};return i.args=t,i.type=e,!0===r&&(i.optional=!0),jt(n)&&(i.enumv=n),function(t){if(!function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}(t))return!1;var e=d(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}(o)&&(i.checker=o),vt(a)&&(i.alias=a),i}var Rt=wt,xt=function(t,e,r){return void 0===r&&(r=!1),new Promise((function(n,o){var a=At(t,e,r);return r?a.error.length?o(a.error):n(a.data):a.length?o(a):n([])}))},zt=function(t,e,r){void 0===r&&(r={});var n=r.optional,o=r.enumv,a=r.checker,i=r.alias;return Pt.apply(null,[t,e,n,o,a,i])},Mt=new WeakMap,Ft=new WeakMap;var Jt=function(){this.__suspend__=null,this.queueStore=new Set},Lt={$suspend:{configurable:!0},$queues:{configurable:!0}};Lt.$suspend.set=function(t){var e=this;if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value!");var r=this.__suspend__;this.__suspend__=t,this.logger("($suspend)","Change from "+r+" --\x3e "+t),!0===r&&!1===t&&setTimeout((function(){e.release()}),1)},Jt.prototype.$queue=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return!0===this.__suspend__&&(this.logger("($queue)","added to $queue",t),this.queueStore.add(t)),this.__suspend__},Lt.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},Jt.prototype.release=function(){var t=this,e=this.queueStore.size;if(this.logger("(release)","Release was called "+e),e>0){var r=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",r),r.forEach((function(e){t.logger(e),Reflect.apply(t.$trigger,t,e)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(Jt.prototype,Lt);var Ht=function(t){function e(e){if("function"!=typeof e)throw new Error("Just die here the logger is not a function!");t.call(this,{logger:e})}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={name:{configurable:!0}};return r.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(e.prototype,r),e}(function(t){function e(e){void 0===e&&(e={}),t.call(this,e)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={$done:{configurable:!0}};return e.prototype.logger=function(){},e.prototype.$on=function(t,e,r){var n=this;void 0===r&&(r=null);this.validate(t,e);var o=this.takeFromStore(t);if(!1===o)return this.logger("($on)",t+" callback is not in lazy store"),this.addToNormalStore(t,"on",e,r);this.logger("($on)",t+" found in lazy store");var a=0;return o.forEach((function(o){var i=o[0],u=o[1],c=o[2];if(c&&"on"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);n.logger("($on)","call run on "+t),n.run(e,i,r||u),a+=n.addToNormalStore(t,"on",e,r||u)})),a},e.prototype.$once=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=this.takeFromStore(t);this.normalStore;if(!1===n)return this.logger("($once)",t+" not in the lazy store"),this.addToNormalStore(t,"once",e,r);this.logger("($once)",n);var o=Array.from(n)[0],a=o[0],i=o[1],u=o[2];if(u&&"once"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);this.logger("($once)","call run for "+t),this.run(e,a,r||i),this.$off(t)},e.prototype.$only=function(t,e,r){var n=this;void 0===r&&(r=null),this.validate(t,e);var o=!1,a=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger("($only)",t+" add to store"),o=this.addToNormalStore(t,"only",e,r)),!1!==a)&&(this.logger("($only)",t+" found data in lazy store to execute"),Array.from(a).forEach((function(o){var a=o[0],i=o[1],u=o[2];if(u&&"only"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);n.logger("($only)","call run for "+t),n.run(e,a,r||i)})));return o},e.prototype.$onlyOnce=function(t,e,r){void 0===r&&(r=null),this.validate(t,e);var n=!1,o=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger("($onlyOnce)",t+" add to store"),n=this.addToNormalStore(t,"onlyOnce",e,r)),!1!==o){this.logger("($onlyOnce)",o);var a=Array.from(o)[0],i=a[0],u=a[1],c=a[2];if(c&&"onlyOnce"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);this.logger("($onlyOnce)","call run for "+t),this.run(e,i,r||u),this.$off(t)}return n},e.prototype.$replace=function(t,e,r,n){if(void 0===r&&(r=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,e),Reflect.apply(o,this,[t,e,r])}throw new Error(n+" is not supported!")},e.prototype.$trigger=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,a=this.normalStore;if(this.logger("($trigger)","normalStore",a),a.has(t)){var i=this.$queue(t,e,r,n);if(this.logger("($trigger)",t,"found; add to queue: ",i),!0===i)return this.logger("($trigger)",t,"not executed. Exit now."),!1;for(var u=Array.from(a.get(t)),c=u.length,s=!1,l=0;l0;)n[o]=arguments[o+2];if(t.has(e)?(this.logger("(addToStore)",e+" existed"),r=t.get(e)):(this.logger("(addToStore)","create new Set for "+e),r=new Set),n.length>2)if(Array.isArray(n[0])){var a=n[2];this.checkTypeInLazyStore(e,a)||r.add(n)}else this.checkContentExist(n,r)||(this.logger("(addToStore)","insert new",n),r.add(n));else r.add(n);return t.set(e,r),[t,r.size]},e.prototype.checkContentExist=function(t,e){return!!Array.from(e).filter((function(e){return e[0]===t[0]})).length},e.prototype.checkTypeInStore=function(t,e){this.validateEvt(t,e);var r=this.$get(t,!0);return!1===r||!r.filter((function(t){var r=t[3];return e!==r})).length},e.prototype.checkTypeInLazyStore=function(t,e){this.validateEvt(t,e);var r=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",r),!!r&&!!Array.from(r).filter((function(t){return t[2]!==e})).length},e.prototype.addToNormalStore=function(t,e,r,n){if(void 0===n&&(n=null),this.logger("(addToNormalStore)",t,e,"try to add to normal store"),this.checkTypeInStore(t,e)){this.logger("(addToNormalStore)",e+" can add to "+t+" normal store");var o=this.hashFnToKey(r),a=[this.normalStore,t,o,r,n,e],i=Reflect.apply(this.addToStore,this,a),u=i[0],c=i[1];return this.normalStore=u,c}return!1},e.prototype.addToLazyStore=function(t,e,r,n){void 0===e&&(e=[]),void 0===r&&(r=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(e),r];n&&o.push(n);var a=Reflect.apply(this.addToStore,this,o),i=a[0],u=a[1];return this.lazyStore=i,u},e.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},r.normalStore.set=function(t){Mt.set(this,t)},r.normalStore.get=function(){return Mt.get(this)},r.lazyStore.set=function(t){Ft.set(this,t)},r.lazyStore.get=function(){return Ft.get(this)},e.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,e){return(t=(t<<5)-t+e.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(e.prototype,r),e}(Jt)));function Yt(t){var e,r,n=t.contract;return t.enableAuth?function(t,e){void 0===e&&(e=!1);var r=gt(t);if(!1===r){if(e)return t;throw new ft("socket not found in contract!")}var n,o={},a=0;for(var i in r){var u=r[i],c=u.namespace;c&&(o[c]||(++a,o[c]={}),o[c][i]=u,n||u.public&&(n=c))}return{size:a,nspSet:o,publicNamespace:n}}(n):((r={}).nspSet=((e={}).jsonql=function(t){var e=gt(t);if(!1!==e)return e;throw new it("Missing property in contract!")}(n),e),r.publicNamespace="jsonql",r)}var It=function(t,e){K(e).forEach((function(e){t.$off(G(e,"emit"))}))};var Ut=function(t,e,r){var n=r.useCallbackStyle,o=r.log,a=n?"error":"onError",i=n?"result":"onResult";e.$only(G(t,"emit"),(function(r,n){o("[notLoginHandler] hijack the ws call",t,r,n);var u={message:"NOT LOGIN"};e.$call(G(t,r,a),[u]),e.$call(G(t,r,i),[{error:u}])}))};function Wt(t,e,r,n,o,a){var i=function(t){return t.length>1&&t[0]}(o),u=!1,c=t.log;o.forEach((function(o){if(u=i===o,a[o]){c("[call bindWsHandler]",u,o);var s=[o,a[o],r,u,t];if("socket.io"===t.serverType){var l=e.nspSet;s.push(l[o])}Reflect.apply(n,null,s)}else Ut(o,r,t)})),r.$on("__logout__",(function(){c("LOGOUT_EVENT_NAME"),function(t,e,r,n){void 0===n&&(n={});var o=n.useCallbackStyle?"error":"onError";e.forEach((function(e){t.$call(G(e,o),[{message:r,namespace:e}])}))}(r,o,"__logout__"),o.forEach((function(e){It(r,e),a[e]=!1,Ut(e,r,t)}))}))}var Kt=["__reply__","__event__","__data__"],Dt=function(t){var e,r=t.data;if(!1!==(e=function(t){var e=t.data;return!!e&&(Kt.filter((function(t){return D(e,t)})).length===Kt.length&&e)}(Rt(r)?JSON.parse(r):r)))return{resolverName:e.__event__,data:e.__data__,type:e.__reply__};throw new ft("payload can not be decoded",t)},Gt=function(t,e,r,n,o){var a=[e];r&&a.push(r),a.push(o);var i=Reflect.apply(G,null,a),u=n.data||n;t.$trigger(i,[u])};function Vt(t,e,r,n,o){var a=o.useCallbackStyle,i=o.log;i("wsMainHandler log test");var u=a?"ready":"onReady",c=a?"login":"onLogin",s=a?"message":"onMessage",l=a?"result":"onResult",f=a?"error":"onError";e.onopen=function(){i("ws.onopen listened"),r.$call(u,t),n&&(i("isPrivate and fire the "+c),r.$call(c,t)),r.$only(G(t,"emit"),(function(t,r){i("calling server",t,r),e.send(function(t,e,r){return void 0===e&&(e=[]),void 0===r&&(r=!1),JSON.stringify(yt(t,e,r))}(t,r))}))},e.onmessage=function(e){try{var n=Dt(e),o=n.resolverName,a=n.type;switch(i("Hear from server",a,n),a){case"emit":var u=G(t,o,s),c=r.$trigger(u,[n]);i("EMIT_REPLY_TYPE",u,c);break;case"acknowledge":var p=G(t,o,l);r.$trigger(p,[n]);break;case"error":i("ERROR_TYPE"),Gt(r,t,o,n,f);break;default:i("Unhandled event!",n),Gt(r,t,o,n,f)}}catch(e){console.error("ws.onmessage error",e),Gt(r,t,!1,e,f)}},e.onclose=function(){i("ws.onclose callback")},r.$on("__logout__",(function(){try{i("terminate ws connection"),e.terminate()}catch(t){console.error("ws.terminate error",t)}}))}var Bt=function(t,e,r){var n,o=e.nspSet,a=e.publicNamespace,i=!1,u=[],c={};if(t.enableAuth)i=!0,c=(u=function(t,e){var r=[];for(var n in t)n===e?r[1]=n:r[0]=n;return r}(o,a)).map((function(e,n){var o,a,i;return 0===n?r?(t.token=r,(o={})[e]=function(t,e){var r=e.hostname,n=e.wssPath,o=e.token,a=e.wsOptions,i=e.nspAuthClient,u=t?[r,t].join("/"):n;if(o&&"string"!=typeof o)throw new Error("Expect token to be string, but got "+o);return i(u,o,a)}(e,t),o):((a={})[e]=!1,a):((i={})[e]=mt(e,t),i)})).reduce((function(t,e){return Object.assign(t,e)}),{});else{var s=(n=o,Object.keys(n)[0]);u.push(s),c[s]=mt(!1,t)}return{nsps:c,namespaces:u,login:i}};var Qt,Xt,Zt,te=(Xt=n(Qt=e),Zt=n(Qt,!0),function(t,e,r){t.nspClient=Xt,t.nspAuthClient=Zt;var n=t.log;return n&&"function"==typeof n&&(n("@jsonql/ws ee",r.name),n("@jsonql/ws createClientResolver",t)),function(t,e,r){var n=[t,e,r,Vt],o=t.token,a=t.log,i=Bt(t,e,o),u=i.nsps,c=i.namespaces,s=i.login;return Reflect.apply(Wt,null,n.concat([c,u])),s&&r.$only("__login__",(function(o){a("createClient LOGIN_EVENT_NAME"),It(r,c);var i=Bt(t,e,o);Reflect.apply(Wt,null,n.concat([i.namespaces,i.nsps]))})),{opts:t,nspMap:e,ee:r}}(t,e,r)});function ee(t,e,r){D(t,"error")?r(t.error):D(t,"data")?e(t.data):r({message:"UKNNOWN RESULT!",error:t})}function re(t,e,r,n,o){void 0===o&&(o=[]);var a=G(e,"emit"),i=n?"result":"onResult";return t.$trigger(a,[r,K(o)]),new Promise((function(n,o){t.$on(G(e,r,i),(function(t){ee(t,n,o)}))}))}var ne=function(t,e,r,n,o,a){return X(t,"send",(function(t){var i=a?"error":"onError";xt(K(t),o.params,!0).then((function(o){if(!o.error||!o.error.length)return re(e,r,n,a,t);e.$call(G(r,n,i),[new lt(n,o.error)])})).catch((function(t){e.$call(G(r,n,i),[new lt(n,t)])}))}),(function(){return function(){for(var t=[],i=arguments.length;i--;)t[i]=arguments[i];return xt(t,o.params,!0).then((function(t){return re(e,r,n,a,t)})).catch(ht)}}))};function oe(t,e,r,n,o){return[Z(t,"on",(function(t,o){if(Rt(t)&&V(o))switch(t){case"result":e.$on(G(r,n,"onResult"),(function(t){ee(t,o,(function(t){e.$trigger(G(r,n,"onError"),t)}))}));break;case"message":e.$only(G(r,n,"onMessage"),(function(t){ee(t,o,(function(t){e.$trigger(G(r,n,"onError"),t)}))}));break;case"ready":e.$only(G(r,n,"onError"),o);break;default:e.$trigger(G(r,n,"onError"),new ft(n,"Unknown event name "+t+"!"))}})),e,r,n,o]}var ae=function(t,e,r,n,o,a){return[Z(t,"myNamespace",r),e,r,n,o,a]},ie=function(t,e,r,n,o,a){return[X(t,"onResult",(function(t){V(t)&&e.$on(G(r,n,"onResult"),(function(o){ee(o,t,(function(t){e.$trigger(G(r,n,"onError"),t)}))}))})),e,r,n,o,a]},ue=function(t,e,r,n,o,a){return[X(t,"onMessage",(function(t){if(V(t)){e.$only(G(r,n,"onMessage"),(function(o){ee(o,t,(function(t){e.$trigger(G(r,n,"onError"),t)}))}))}})),e,r,n,o,a]},ce=function(t,e,r,n,o,a){return[X(t,"onError",(function(t){V(t)&&e.$only(G(r,n,"onError"),t)})),e,r,n,o,a]};function se(t,e,r,n,o,a){var i=[ae];a?i.push(oe):i.push(ie,ue,ce),i.push(ne);var u=Reflect.apply(B,null,i);return Reflect.apply(u,null,[n,o,t,e,r,a])}function le(t,e,r,n,o){return function(){for(var a=[],i=arguments.length;i--;)a[i]=arguments[i];return xt(a,n.params,!0).then((function(n){return re(t,e,r,o,n)})).catch(ht)}}var fe,pe,he=function(t,e,r){return[Z(t,r.loginHandlerName,(function(t){if(t&&Rt(t))return e.$trigger("__login__",[t]);throw new lt(r.loginHandlerName,"Unexpected token "+t)})),e,r]},ge=function(t,e,r){return Z(t,r.logoutHandlerName,(function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];e.$trigger("__logout__",t)}))};function de(t,e,r){var n={},o=e.nspSet,a=t.useCallbackStyle;for(var i in o){var u=o[i];for(var c in u){var s=u[c];n=Z(n,c,se(i,c,s,le(r,i,c,s,a),r,a))}}return n.devHelpers={getNsp:function(){return Object.keys(o)},getVer:function(){return t.version||"NOT SET"}},Promise.resolve(n)}function ve(t,e,r){var n=e.nspSet,o=t.useCallbackStyle,a=t.enableAuth,i=[de];return o?i.push((function(t){return function(t,e,r,n){return Z(t,"on",(function(t,n){if(Rt(t)&&V(n))switch(t){case"error":for(var o in r)e.$on(G(o,"error"),n);break;case"login":e.$only("login",n);break;case"ready":e.$on("ready",n);break;default:e.$trigger("error",new ft("on","Unknown event name "+t+"!"))}}))}(t,r,n)})):(i.push((function(t){return function(t,e,r){return X(t,"onError",(function(t){if(V(t))for(var n in r)e.$on(G(n,"onError"),t)}))}(t,r,n)}),(function(t){return function(t,e,r){return X(t,"onReady",(function(t){V(t)&&e.$on("onReady",t)}))}(t,r)})),a&&i.push((function(e){return function(t,e,r){return r.enableAuth?X(t,"onLogin",(function(t){V(t)&&e.$only("onLogin",t)})):t}(e,r,t)}))),a&&i.push((function(e){return function(t,e,r){return r.enableAuth?B(he,ge)(t,e,r):t}(e,r,t)})),Reflect.apply(Q,null,i)(t,e,r)}var ye=["roundtip","handshake"],me={useCallbackStyle:zt(!1,["boolean"]),loginHandlerName:zt("login",["string"]),logoutHandlerName:zt("logout",["string"]),loginMethod:zt("handshake",["string"],(fe={},fe.enumv=ye,fe)),useJwt:zt(!0,["boolean","string"]),authStrKey:zt(null,["string"]),hostname:zt(!1,["string"]),namespace:zt("jsonql",["string"]),wsOptions:zt({},["object"]),contract:zt({},["object"],(pe={},pe.checker=function(t){return!!function(t){return j(t)&&(D(t,"query")||D(t,"mutation")||D(t,"socket"))}(t)&&t},pe)),enableAuth:zt(!1,["boolean"]),token:zt(!1,["string"])};function be(t){return Promise.resolve(t).then((function(t){var e;return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new lt(t)}}()),t.wssPath=(e=[t.hostname,t.namespace].join("/"),"ws"===t.serverType?e.replace("http://","ws://"):e),t}))}var _e=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];Reflect.apply(console.info,console,["[jsonql-ws-client-core]"].concat(t))},we=function(t){var e=t.log,r=t.eventEmitter;return e("CHECKED_KEY",t.__checked__),r?(e("eventEmitter is:",r.name),r):(e("Create a new Event Emitter"),new Ht(t.log))},Se=function(t){var e=t.log;return e&&"function"==typeof e||(t.log=_e),t.log("--- wsClientCore config opts ---",t),t};var Ee={version:"version: 1.1.0 module: cjs-module",serverType:"ws"},ke=Object.assign({},me,{}),je=Object.assign({},{eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:""},Ee);var $e,Oe=($e=te,function(t){return Promise.resolve(t).then(be).then((function(t){return function(t,e){return Promise.resolve(e).then(Se).then((function(t){return{opts:t,nspMap:Yt(t),ee:we(t)}})).then((function(e){var r=e.opts,n=e.nspMap,o=e.ee;return t(r,n,o)})).then((function(t){return ve(t.opts,t.nspMap,t.ee)})).catch((function(t){console.error("jsonql-ws-core-client init error",t)}))}($e,t)}))});exports.createWsClient=Oe,exports.jsonqlWsClientAppProps=ke,exports.jsonqlWsConstProps=je; +//# sourceMappingURL=node.js.map diff --git a/packages/@jsonql/ws/node.js.map b/packages/@jsonql/ws/node.js.map new file mode 100644 index 00000000..dec3b7b6 --- /dev/null +++ b/packages/@jsonql/ws/node.js.map @@ -0,0 +1 @@ +{"version":3,"file":"node.js","sources":[],"sourcesContent":[],"names":[],"mappings":""} \ No newline at end of file diff --git a/packages/@jsonql/ws/package.json b/packages/@jsonql/ws/package.json index 7cd6a741..80ecf2ed 100644 --- a/packages/@jsonql/ws/package.json +++ b/packages/@jsonql/ws/package.json @@ -21,7 +21,7 @@ "build:umd": "TARGET=umd rollup -c", "build:cjs:module": "TARGET=cjs-module rollup -c", "build:test": "npm run build:cjs && npm run build:umd && npm run build:cjs:module && npm run build:umd:module", - "build": "NODE_ENV=production npm run build:cjs && NODE_ENV=production npm run build:umd", + "build": "NODE_ENV=production npm run build:cjs && NODE_ENV=production npm run build:cjs:module && NODE_ENV=production npm run build:umd", "test:browser:basic": "npm run build:umd && DEBUG=jsonql-ws-client*,server-io-core* node ./tests/browser/run-qunit.js", "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", diff --git a/packages/@jsonql/ws/rollup.config.js b/packages/@jsonql/ws/rollup.config.js index 2266c5c6..df48dbd3 100644 --- a/packages/@jsonql/ws/rollup.config.js +++ b/packages/@jsonql/ws/rollup.config.js @@ -51,21 +51,24 @@ if (process.env.NODE_ENV === 'production') { } plugins.push( size() ) -let inFile, outFile +let inFile, outFile, _target switch (target) { case 'cjs': inFile = 'src/node.js' outFile = join(__dirname, 'main.js') + _target = 'cjs' break case 'cjs-module': inFile = 'src/node-module.js' outFile = join(__dirname, 'node.js') + _target = 'cjs' break case 'umd': default: inFile = 'index.js' outFile = join(__dirname, 'dist', `jsonql-ws-client.${target}.js`) + _target = 'umd' break } @@ -74,7 +77,7 @@ let config = { output: { name: 'jsonqlWsClient', file: outFile, - format: target, + format: _target, sourcemap: true, globals: { 'path': 'path', diff --git a/packages/@jsonql/ws/src/node-module.js b/packages/@jsonql/ws/src/node-module.js index b1a9d3b4..260453c1 100644 --- a/packages/@jsonql/ws/src/node-module.js +++ b/packages/@jsonql/ws/src/node-module.js @@ -4,7 +4,7 @@ import { jsonqlWsClientAppProps, jsonqlWsConstProps, generateWsClient -} from './src/module' +} from './module' const createWsClient = generateWsClient(nodeWsClientResolver) -- Gitee From dfad1077f57971b96cbc8f31b10a5304ad2bd35a Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 4 Mar 2020 08:17:40 +0800 Subject: [PATCH 24/26] still completely fucked --- packages/@jsonql/ws/main.js | 8707 ++++++++++++++++- packages/@jsonql/ws/main.js.map | 2 +- packages/@jsonql/ws/src/node.js | 2 +- .../{node-org.js => tests/previous/node.js} | 0 .../previous/node.js.map} | 0 .../@jsonql/ws/tests/ws-client-basic.test.js | 16 +- 6 files changed, 8718 insertions(+), 9 deletions(-) rename packages/@jsonql/ws/{node-org.js => tests/previous/node.js} (100%) rename packages/@jsonql/ws/{node-org.js.map => tests/previous/node.js.map} (100%) diff --git a/packages/@jsonql/ws/main.js b/packages/@jsonql/ws/main.js index c3cf670b..af4607df 100644 --- a/packages/@jsonql/ws/main.js +++ b/packages/@jsonql/ws/main.js @@ -1,2 +1,8707 @@ -"use strict";var t,r=(t=require("ws"))&&"object"==typeof t&&"default"in t?t.default:t,e=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 406},e.name.get=function(){return"Jsonql406Error"},Object.defineProperties(r,e),r}(Error),n=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 500},e.name.get=function(){return"Jsonql500Error"},Object.defineProperties(r,e),r}(Error),o=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 403},e.name.get=function(){return"JsonqlForbiddenError"},Object.defineProperties(r,e),r}(Error),a=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 401},e.name.get=function(){return"JsonqlAuthorisationError"},Object.defineProperties(r,e),r}(Error),i=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 401},e.name.get=function(){return"JsonqlContractAuthError"},Object.defineProperties(r,e),r}(Error),u=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 500},e.name.get=function(){return"JsonqlResolverAppError"},Object.defineProperties(r,e),r}(Error),c=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={statusCode:{configurable:!0},name:{configurable:!0}};return e.statusCode.get=function(){return 404},e.name.get=function(){return"JsonqlResolverNotFoundError"},Object.defineProperties(r,e),r}(Error),s=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlEnumError"},Object.defineProperties(r,e),r}(Error),f=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlTypeError"},Object.defineProperties(r,e),r}(Error),l=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlCheckerError"},Object.defineProperties(r,e),r}(Error),p=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlValidationError"},Object.defineProperties(r,e),r}(Error),h=function(t){function r(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];t.apply(this,e),this.message=e[0],this.detail=e[1],this.className=r.name,t.captureStackTrace&&t.captureStackTrace(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0},statusCode:{configurable:!0}};return e.name.get=function(){return"JsonqlError"},e.statusCode.get=function(){return-1},Object.defineProperties(r,e),r}(Error),v=function(t){function r(e,n){t.call(this,n),this.statusCode=e,this.className=r.name}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"JsonqlServerError"},Object.defineProperties(r,e),r}(Error);function g(t){if(Array.isArray(t))throw new p("",t);var r=t.message||"No message",g=t.detail||t;switch(!0){case t instanceof e:throw new e(r,g);case t instanceof n:throw new n(r,g);case t instanceof o:throw new o(r,g);case t instanceof a:throw new a(r,g);case t instanceof i:throw new i(r,g);case t instanceof u:throw new u(r,g);case t instanceof c:throw new c(r,g);case t instanceof s:throw new s(r,g);case t instanceof f:throw new f(r,g);case t instanceof l:throw new l(r,g);case t instanceof p:throw new p(r,g);case t instanceof v:throw new v(r,g);default:throw new h(r,g)}}var y="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},d="object"==typeof y&&y&&y.Object===Object&&y,b="object"==typeof self&&self&&self.Object===Object&&self,_=d||b||Function("return this")(),m=_.Symbol;function w(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 a=Array(o);++n-1;);return e}(n,o),function(t,r){for(var e=t.length;e--&&M(r,t[e],0)>-1;);return e}(n,o)+1).join("")}var Z=function(t){return!!j(t)||null!=t&&""!==X(t)};function tt(t){return function(t){return"number"==typeof t||P(t)&&"[object Number]"==A(t)}(t)&&t!=+t}function rt(t){return"string"==typeof t||!j(t)&&P(t)&&"[object String]"==A(t)}var et=function(t){return!rt(t)&&!tt(parseFloat(t))},nt=function(t){return""!==X(t)&&rt(t)},ot=function(t){return null!=t&&"boolean"==typeof t},at=function(t,r){return void 0===r&&(r=!0),void 0!==t&&""!==t&&""!==X(t)&&(!1===r||!0===r&&null!==t)},it=function(t){switch(t){case"number":return et;case"string":return nt;case"boolean":return ot;default:return at}},ut=function(t,r){return void 0===r&&(r=""),!!j(t)&&(""===r||""===X(r)||!(t.filter((function(t){return!it(r)(t)})).length>0))},ct=function(t){if(t.indexOf("array.<")>-1&&t.indexOf(">")>-1){var r=t.replace("array.<","").replace(">","");return r.indexOf("|")?r.split("|"):[r]}return!1},st=function(t,r){var e=t.arg;return r.length>1?!e.filter((function(t){return!(r.length>r.filter((function(r){return!it(r)(t)})).length)})).length:r.length>r.filter((function(t){return!ut(e,t)})).length};function ft(t,r){return function(e){return t(r(e))}}var lt=ft(Object.getPrototypeOf,Object),pt=Function.prototype,ht=Object.prototype,vt=pt.toString,gt=ht.hasOwnProperty,yt=vt.call(Object);function dt(t){if(!P(t)||"[object Object]"!=A(t))return!1;var r=lt(t);if(null===r)return!0;var e=gt.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&vt.call(e)==yt}var bt,_t=function(t,r,e){for(var n=-1,o=Object(t),a=e(t),i=a.length;i--;){var u=a[bt?i:++n];if(!1===r(o[u],u,o))break}return t};function mt(t){return P(t)&&"[object Arguments]"==A(t)}var wt=Object.prototype,jt=wt.hasOwnProperty,Ot=wt.propertyIsEnumerable,St=mt(function(){return arguments}())?mt:function(t){return P(t)&&jt.call(t,"callee")&&!Ot.call(t,"callee")};var kt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Et=kt&&"object"==typeof module&&module&&!module.nodeType&&module,$t=Et&&Et.exports===kt?_.Buffer:void 0,Tt=($t?$t.isBuffer:void 0)||function(){return!1},At=/^(?:0|[1-9]\d*)$/;function Pt(t,r){var e=typeof t;return!!(r=null==r?9007199254740991:r)&&("number"==e||"symbol"!=e&&At.test(t))&&t>-1&&t%1==0&&t-1&&t%1==0&&t<=9007199254740991}var zt={};zt["[object Float32Array]"]=zt["[object Float64Array]"]=zt["[object Int8Array]"]=zt["[object Int16Array]"]=zt["[object Int32Array]"]=zt["[object Uint8Array]"]=zt["[object Uint8ClampedArray]"]=zt["[object Uint16Array]"]=zt["[object Uint32Array]"]=!0,zt["[object Arguments]"]=zt["[object Array]"]=zt["[object ArrayBuffer]"]=zt["[object Boolean]"]=zt["[object DataView]"]=zt["[object Date]"]=zt["[object Error]"]=zt["[object Function]"]=zt["[object Map]"]=zt["[object Number]"]=zt["[object Object]"]=zt["[object RegExp]"]=zt["[object Set]"]=zt["[object String]"]=zt["[object WeakMap]"]=!1;var Ct,xt="object"==typeof exports&&exports&&!exports.nodeType&&exports,Rt=xt&&"object"==typeof module&&module&&!module.nodeType&&module,qt=Rt&&Rt.exports===xt&&d.process,Mt=function(){try{var t=Rt&&Rt.require&&Rt.require("util").types;return t||qt&&qt.binding&&qt.binding("util")}catch(t){}}(),Ft=Mt&&Mt.isTypedArray,Lt=Ft?(Ct=Ft,function(t){return Ct(t)}):function(t){return P(t)&&Nt(t.length)&&!!zt[A(t)]},Jt=Object.prototype.hasOwnProperty;function It(t,r){var e=j(t),n=!e&&St(t),o=!e&&!n&&Tt(t),a=!e&&!n&&!o&&Lt(t),i=e||n||o||a,u=i?function(t,r){for(var e=-1,n=Array(t);++e-1},tr.prototype.set=function(t,r){var e=this.__data__,n=Xt(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this};var rr,er=_["__core-js_shared__"],nr=(rr=/[^.]+$/.exec(er&&er.keys&&er.keys.IE_PROTO||""))?"Symbol(src)_1."+rr:"";var or=Function.prototype.toString;function ar(t){if(null!=t){try{return or.call(t)}catch(t){}try{return t+""}catch(t){}}return""}var ir=/^\[object .+?Constructor\]$/,ur=Function.prototype,cr=Object.prototype,sr=ur.toString,fr=cr.hasOwnProperty,lr=RegExp("^"+sr.call(fr).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function pr(t){return!(!Bt(t)||function(t){return!!nr&&nr in t}(t))&&(Wt(t)?lr:ir).test(ar(t))}function hr(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return pr(e)?e:void 0}var vr=hr(_,"Map"),gr=hr(Object,"create");var yr=Object.prototype.hasOwnProperty;var dr=Object.prototype.hasOwnProperty;function br(t){var r=-1,e=null==t?0:t.length;for(this.clear();++ru))return!1;var s=a.get(t);if(s&&a.get(r))return s==r;var f=-1,l=!0,p=2&e?new jr:void 0;for(a.set(t,r),a.set(r,t);++fr.type.filter((function(t){var r;return void 0===e||(!1!==(r=ct(t))?!st({arg:e},r):!it(t)(e))})).length)})).length}return!1},be=function(t,r){var e,n,o,a,i;switch(!0){case"object"===t:return o=(n=r).arg,a=n.param,i=[o],Array.isArray(a.keys)&&a.keys.length&&i.push(a.keys),!Reflect.apply(de,null,i);case"array"===t:return!ut(r.arg);case!1!==(e=ct(t)):return!st(r,e);default:return!it(t)(r.arg)}},_e=function(t,r){return void 0!==t?t:!0===r.optional&&void 0!==r.defaultvalue?r.defaultvalue:null},me=function(t,r,e){var n;void 0===e&&(e=!1);var o=function(t,r){if(!ut(r))throw new h("params is not an array! Did something gone wrong when you generate the contract.json?");if(0===r.length)return[];if(!ut(t))throw new h("args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)");switch(!0){case t.length==r.length:return t.map((function(t,e){return{arg:t,index:e,param:r[e]}}));case!0===r[0].variable:var e=r[0].type;return t.map((function(t,n){return{arg:t,index:n,param:r[n]||{type:e,name:"_"}}}));case t.lengthr.length:var n=r.length,o=["any"];return t.map((function(t,e){var a=e>=n||!!r[e].optional,i=r[e]||{type:o,name:"_"+e};return{arg:a?_e(t,i):t,index:e,param:i,optional:a}}));default:throw new h("Could not understand your arguments and parameter structure!",{args:t,params:r})}}(t,r),a=o.filter((function(t){return!0===t.optional||!0===t.param.optional?function(t){var r=t.arg,e=t.param;return!!Z(r)&&!(e.type.length>e.type.filter((function(r){return be(r,t)})).length)}(t):!(t.param.type.length>t.param.type.filter((function(r){return be(r,t)})).length)}));return e?((n={}).error=a,n.data=o.map((function(t){return t.arg})),n):a},we=function(){try{var t=hr(Object,"defineProperty");return t({},"",{}),t}catch(t){}}();function je(t,r,e){"__proto__"==r&&we?we(t,r,{configurable:!0,enumerable:!0,value:e,writable:!0}):t[r]=e}function Oe(t,r,e){(void 0===e||Qt(t[r],e))&&(void 0!==e||r in t)||je(t,r,e)}var Se="object"==typeof exports&&exports&&!exports.nodeType&&exports,ke=Se&&"object"==typeof module&&module&&!module.nodeType&&module,Ee=ke&&ke.exports===Se?_.Buffer:void 0,$e=Ee?Ee.allocUnsafe:void 0;function Te(t,r){var e,n,o=r?(e=t.buffer,n=new e.constructor(e.byteLength),new kr(n).set(new kr(e)),n):t.buffer;return new t.constructor(o,t.byteOffset,t.length)}var Ae=Object.create,Pe=function(){function t(){}return function(r){if(!Bt(r))return{};if(Ae)return Ae(r);t.prototype=r;var e=new t;return t.prototype=void 0,e}}();function Ne(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var ze=Object.prototype.hasOwnProperty;function Ce(t,r,e){var n=t[r];ze.call(t,r)&&Qt(n,e)&&(void 0!==e||r in t)||je(t,r,e)}var xe=Object.prototype.hasOwnProperty;function Re(t){if(!Bt(t))return function(t){var r=[];if(null!=t)for(var e in Object(t))r.push(e);return r}(t);var r=Dt(t),e=[];for(var n in t)("constructor"!=n||!r&&xe.call(t,n))&&e.push(n);return e}function qe(t){return Yt(t)?It(t,!0):Re(t)}function Me(t){return function(t,r,e,n){var o=!e;e||(e={});for(var a=-1,i=r.length;++a0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(Ue);function Ve(t,r){return He(function(t,r,e){return r=Ie(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,a=Ie(n.length-r,0),i=Array(a);++o1?r[n-1]:void 0,a=n>2?r[2]:void 0;for(o=Be.length>3&&"function"==typeof o?(n--,o):void 0,a&&function(t,r,e){if(!Bt(e))return!1;var n=typeof r;return!!("number"==n?Yt(e)&&Pt(r,e.length):"string"==n&&r in e)&&Qt(e[r],t)}(r[0],r[1],a)&&(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,ln(t))}),Reflect.apply(t,null,e))}};function yn(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))}}function dn(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}function bn(t,r,e,n){void 0===n&&(n=!1);var o=function(t,r){var e=Object.getOwnPropertyDescriptor(t,r);return void 0!==e&&e.value?e.value:e}(t,r);return!1===n&&void 0!==o||Object.defineProperty(t,r,{value:e,writable:n}),t}function _n(t){return!!pn(t,"socket")&&t.socket}var mn=function(t){void 0===t&&(t=!1);var r=Date.now();return t?Math.floor(r/1e3):r};function wn(t,r,e){if(void 0===r&&(r=[]),void 0===e&&(e=!1),rt(t)&&j(r)){var n=function(t){var r;return(r={}).args=t,r}(r);return!0===e?n:function(t,r){var e;return(e={})[t]=r,e.TS=[mn()],e}(t,n)}throw new p("[createQuery] expect resolverName to be string and args to be array!",{resolverName:t,args:r})}var jn=new WeakMap,On=new WeakMap;var Sn=function(){this.__suspend__=null,this.queueStore=new Set},kn={$suspend:{configurable:!0},$queues:{configurable:!0}};kn.$suspend.set=function(t){var r=this;if("boolean"!=typeof t)throw new Error("$suspend only accept Boolean value!");var e=this.__suspend__;this.__suspend__=t,this.logger("($suspend)","Change from "+e+" --\x3e "+t),!0===e&&!1===t&&setTimeout((function(){r.release()}),1)},Sn.prototype.$queue=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return!0===this.__suspend__&&(this.logger("($queue)","added to $queue",t),this.queueStore.add(t)),this.__suspend__},kn.$queues.get=function(){var t=this.queueStore.size;return this.logger("($queues)","size: "+t),t>0?Array.from(this.queueStore):[]},Sn.prototype.release=function(){var t=this,r=this.queueStore.size;if(this.logger("(release)","Release was called "+r),r>0){var e=Array.from(this.queueStore);this.queueStore.clear(),this.logger("queue",e),e.forEach((function(r){t.logger(r),Reflect.apply(t.$trigger,t,r)})),this.logger("Release size "+this.queueStore.size)}},Object.defineProperties(Sn.prototype,kn);var En=function(t){function r(r){if("function"!=typeof r)throw new Error("Just die here the logger is not a function!");t.call(this,{logger:r})}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={name:{configurable:!0}};return e.name.get=function(){return"jsonql-ws-client-core"},Object.defineProperties(r.prototype,e),r}(function(t){function r(r){void 0===r&&(r={}),t.call(this,r)}t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r;var e={$done:{configurable:!0}};return r.prototype.logger=function(){},r.prototype.$on=function(t,r,e){var n=this;void 0===e&&(e=null);this.validate(t,r);var o=this.takeFromStore(t);if(!1===o)return this.logger("($on)",t+" callback is not in lazy store"),this.addToNormalStore(t,"on",r,e);this.logger("($on)",t+" found in lazy store");var a=0;return o.forEach((function(o){var i=o[0],u=o[1],c=o[2];if(c&&"on"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);n.logger("($on)","call run on "+t),n.run(r,i,e||u),a+=n.addToNormalStore(t,"on",r,e||u)})),a},r.prototype.$once=function(t,r,e){void 0===e&&(e=null),this.validate(t,r);var n=this.takeFromStore(t);this.normalStore;if(!1===n)return this.logger("($once)",t+" not in the lazy store"),this.addToNormalStore(t,"once",r,e);this.logger("($once)",n);var o=Array.from(n)[0],a=o[0],i=o[1],u=o[2];if(u&&"once"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);this.logger("($once)","call run for "+t),this.run(r,a,e||i),this.$off(t)},r.prototype.$only=function(t,r,e){var n=this;void 0===e&&(e=null),this.validate(t,r);var o=!1,a=this.takeFromStore(t);(this.normalStore.has(t)||(this.logger("($only)",t+" add to store"),o=this.addToNormalStore(t,"only",r,e)),!1!==a)&&(this.logger("($only)",t+" found data in lazy store to execute"),Array.from(a).forEach((function(o){var a=o[0],i=o[1],u=o[2];if(u&&"only"!==u)throw new Error("You are trying to register an event already been taken by other type: "+u);n.logger("($only)","call run for "+t),n.run(r,a,e||i)})));return o},r.prototype.$onlyOnce=function(t,r,e){void 0===e&&(e=null),this.validate(t,r);var n=!1,o=this.takeFromStore(t);if(this.normalStore.has(t)||(this.logger("($onlyOnce)",t+" add to store"),n=this.addToNormalStore(t,"onlyOnce",r,e)),!1!==o){this.logger("($onlyOnce)",o);var a=Array.from(o)[0],i=a[0],u=a[1],c=a[2];if(c&&"onlyOnce"!==c)throw new Error("You are trying to register an event already been taken by other type: "+c);this.logger("($onlyOnce)","call run for "+t),this.run(r,i,e||u),this.$off(t)}return n},r.prototype.$replace=function(t,r,e,n){if(void 0===e&&(e=null),void 0===n&&(n="on"),this.validateType(n)){this.$off(t);var o=this["$"+n];return this.logger("($replace)",t,r),Reflect.apply(o,this,[t,r,e])}throw new Error(n+" is not supported!")},r.prototype.$trigger=function(t,r,e,n){void 0===r&&(r=[]),void 0===e&&(e=null),void 0===n&&(n=!1),this.validateEvt(t);var o=0,a=this.normalStore;if(this.logger("($trigger)","normalStore",a),a.has(t)){var i=this.$queue(t,r,e,n);if(this.logger("($trigger)",t,"found; add to queue: ",i),!0===i)return this.logger("($trigger)",t,"not executed. Exit now."),!1;for(var u=Array.from(a.get(t)),c=u.length,s=!1,f=0;f0;)n[o]=arguments[o+2];if(t.has(r)?(this.logger("(addToStore)",r+" existed"),e=t.get(r)):(this.logger("(addToStore)","create new Set for "+r),e=new Set),n.length>2)if(Array.isArray(n[0])){var a=n[2];this.checkTypeInLazyStore(r,a)||e.add(n)}else this.checkContentExist(n,e)||(this.logger("(addToStore)","insert new",n),e.add(n));else e.add(n);return t.set(r,e),[t,e.size]},r.prototype.checkContentExist=function(t,r){return!!Array.from(r).filter((function(r){return r[0]===t[0]})).length},r.prototype.checkTypeInStore=function(t,r){this.validateEvt(t,r);var e=this.$get(t,!0);return!1===e||!e.filter((function(t){var e=t[3];return r!==e})).length},r.prototype.checkTypeInLazyStore=function(t,r){this.validateEvt(t,r);var e=this.lazyStore.get(t);return this.logger("(checkTypeInLazyStore)",e),!!e&&!!Array.from(e).filter((function(t){return t[2]!==r})).length},r.prototype.addToNormalStore=function(t,r,e,n){if(void 0===n&&(n=null),this.logger("(addToNormalStore)",t,r,"try to add to normal store"),this.checkTypeInStore(t,r)){this.logger("(addToNormalStore)",r+" can add to "+t+" normal store");var o=this.hashFnToKey(e),a=[this.normalStore,t,o,e,n,r],i=Reflect.apply(this.addToStore,this,a),u=i[0],c=i[1];return this.normalStore=u,c}return!1},r.prototype.addToLazyStore=function(t,r,e,n){void 0===r&&(r=[]),void 0===e&&(e=null),void 0===n&&(n=!1);var o=[this.lazyStore,t,this.toArray(r),e];n&&o.push(n);var a=Reflect.apply(this.addToStore,this,o),i=a[0],u=a[1];return this.lazyStore=i,u},r.prototype.toArray=function(t){return Array.isArray(t)?t:[t]},e.normalStore.set=function(t){jn.set(this,t)},e.normalStore.get=function(){return jn.get(this)},e.lazyStore.set=function(t){On.set(this,t)},e.lazyStore.get=function(){return On.get(this)},r.prototype.hashFnToKey=function(t){return function(t){return t.split("").reduce((function(t,r){return(t=(t<<5)-t+r.charCodeAt(0))&t}),0)}(t.toString())+""},Object.defineProperties(r.prototype,e),r}(Sn)));function $n(t){var r,e,n=t.contract;return t.enableAuth?function(t,r){void 0===r&&(r=!1);var e=_n(t);if(!1===e){if(r)return t;throw new h("socket not found in contract!")}var n,o={},a=0;for(var i in e){var u=e[i],c=u.namespace;c&&(o[c]||(++a,o[c]={}),o[c][i]=u,n||u.public&&(n=c))}return{size:a,nspSet:o,publicNamespace:n}}(n):((e={}).nspSet=((r={}).jsonql=function(t){var r=_n(t);if(!1!==r)return r;throw new c("Missing property in contract!")}(n),r),e.publicNamespace="jsonql",e)}var Tn=function(t,r){ln(r).forEach((function(r){t.$off(hn(r,"emit"))}))};function An(t,r,e){pn(t,"error")?e(t.error):pn(t,"data")?r(t.data):e({message:"UKNNOWN RESULT!",error:t})}function Pn(t,r,e,n,o){void 0===o&&(o=[]);var a=hn(r,"emit"),i=n?"result":"onResult";return t.$trigger(a,[e,ln(o)]),new Promise((function(n,o){t.$on(hn(r,e,i),(function(t){An(t,n,o)}))}))}var Nn=function(t,r,e,n,o,a){return dn(t,"send",(function(t){var i=a?"error":"onError";cn(ln(t),o.params,!0).then((function(o){if(!o.error||!o.error.length)return Pn(r,e,n,a,t);r.$call(hn(e,n,i),[new p(n,o.error)])})).catch((function(t){r.$call(hn(e,n,i),[new p(n,t)])}))}),(function(){return function(){for(var t=[],i=arguments.length;i--;)t[i]=arguments[i];return cn(t,o.params,!0).then((function(t){return Pn(r,e,n,a,t)})).catch(g)}}))};function zn(t,r,e,n,o){return[bn(t,"on",(function(t,o){if(un(t)&&vn(o))switch(t){case"result":r.$on(hn(e,n,"onResult"),(function(t){An(t,o,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}));break;case"message":r.$only(hn(e,n,"onMessage"),(function(t){An(t,o,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}));break;case"ready":r.$only(hn(e,n,"onError"),o);break;default:r.$trigger(hn(e,n,"onError"),new h(n,"Unknown event name "+t+"!"))}})),r,e,n,o]}var Cn=function(t,r,e,n,o,a){return[bn(t,"myNamespace",e),r,e,n,o,a]},xn=function(t,r,e,n,o,a){return[dn(t,"onResult",(function(t){vn(t)&&r.$on(hn(e,n,"onResult"),(function(o){An(o,t,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}))})),r,e,n,o,a]},Rn=function(t,r,e,n,o,a){return[dn(t,"onMessage",(function(t){if(vn(t)){r.$only(hn(e,n,"onMessage"),(function(o){An(o,t,(function(t){r.$trigger(hn(e,n,"onError"),t)}))}))}})),r,e,n,o,a]},qn=function(t,r,e,n,o,a){return[dn(t,"onError",(function(t){vn(t)&&r.$only(hn(e,n,"onError"),t)})),r,e,n,o,a]};function Mn(t,r,e,n,o,a){var i=[Cn];a?i.push(zn):i.push(xn,Rn,qn),i.push(Nn);var u=Reflect.apply(gn,null,i);return Reflect.apply(u,null,[n,o,t,r,e,a])}function Fn(t,r,e,n,o){return function(){for(var a=[],i=arguments.length;i--;)a[i]=arguments[i];return cn(a,n.params,!0).then((function(n){return Pn(t,r,e,o,n)})).catch(g)}}var Ln,Jn,In=function(t,r,e){return[bn(t,e.loginHandlerName,(function(t){if(t&&un(t))return r.$trigger("__login__",[t]);throw new p(e.loginHandlerName,"Unexpected token "+t)})),r,e]},Un=function(t,r,e){return bn(t,e.logoutHandlerName,(function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];r.$trigger("__logout__",t)}))};function Dn(t,r,e){var n={},o=r.nspSet,a=t.useCallbackStyle;for(var i in o){var u=o[i];for(var c in u){var s=u[c];n=bn(n,c,Mn(i,c,s,Fn(e,i,c,s,a),e,a))}}return n.devHelpers={getNsp:function(){return Object.keys(o)},getVer:function(){return t.version||"NOT SET"}},Promise.resolve(n)}function Hn(t,r,e){var n=r.nspSet,o=t.useCallbackStyle,a=t.enableAuth,i=[Dn];return o?i.push((function(t){return function(t,r,e,n){return bn(t,"on",(function(t,n){if(un(t)&&vn(n))switch(t){case"error":for(var o in e)r.$on(hn(o,"error"),n);break;case"login":r.$only("login",n);break;case"ready":r.$on("ready",n);break;default:r.$trigger("error",new h("on","Unknown event name "+t+"!"))}}))}(t,e,n)})):(i.push((function(t){return function(t,r,e){return dn(t,"onError",(function(t){if(vn(t))for(var n in e)r.$on(hn(n,"onError"),t)}))}(t,e,n)}),(function(t){return function(t,r,e){return dn(t,"onReady",(function(t){vn(t)&&r.$on("onReady",t)}))}(t,e)})),a&&i.push((function(r){return function(t,r,e){return e.enableAuth?dn(t,"onLogin",(function(t){vn(t)&&r.$only("onLogin",t)})):t}(r,e,t)}))),a&&i.push((function(r){return function(t,r,e){return e.enableAuth?gn(In,Un)(t,r,e):t}(r,e,t)})),Reflect.apply(yn,null,i)(t,r,e)}var Vn=["roundtip","handshake"],Bn={useCallbackStyle:sn(!1,["boolean"]),loginHandlerName:sn("login",["string"]),logoutHandlerName:sn("logout",["string"]),loginMethod:sn("handshake",["string"],(Ln={},Ln.enumv=Vn,Ln)),useJwt:sn(!0,["boolean","string"]),authStrKey:sn(null,["string"]),hostname:sn(!1,["string"]),namespace:sn("jsonql",["string"]),wsOptions:sn({},["object"]),contract:sn({},["object"],(Jn={},Jn.checker=function(t){return!!function(t){return dt(t)&&(pn(t,"query")||pn(t,"mutation")||pn(t,"socket"))}(t)&&t},Jn)),enableAuth:sn(!1,["boolean"]),token:sn(!1,["string"])},Wn={eventEmitter:null,nspClient:null,nspAuthClient:null,wssPath:""};function Yn(t){return Promise.resolve(t).then((function(t){var r;return t.hostname||(t.hostname=function(){try{return[window.location.protocol,window.location.host].join("//")}catch(t){throw new p(t)}}()),t.wssPath=(r=[t.hostname,t.namespace].join("/"),"ws"===t.serverType?r.replace("http://","ws://"):r),t}))}function Kn(t,r,e){return function(t,r,e){var n=Object.assign(Wn,e),o=Object.assign(Bn,r);return fn(t,o,n)}(t,r,e).then(Yn)}var Gn=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];Reflect.apply(console.info,console,["[jsonql-ws-client-core]"].concat(t))},Qn=function(t){var r=t.log,e=t.eventEmitter;return r("CHECKED_KEY",t.__checked__),e?(r("eventEmitter is:",e.name),e):(r("Create a new Event Emitter"),new En(t.log))},Xn=function(t){var r=t.log;return r&&"function"==typeof r||(t.log=Gn),t.log("--- wsClientCore config opts ---",t),t};function Zn(t,r,e){return void 0===r&&(r={}),void 0===e&&(e={}),function(n){return void 0===n&&(n={}),Kn(n,r,e).then((function(r){return function(t,r){return Promise.resolve(r).then(Xn).then((function(t){return{opts:t,nspMap:$n(t),ee:Qn(t)}})).then((function(r){var e=r.opts,n=r.nspMap,o=r.ee;return t(e,n,o)})).then((function(t){return Hn(t.opts,t.nspMap,t.ee)})).catch((function(t){console.error("jsonql-ws-core-client init error",t)}))}(t,r)}))}}var to={version:"version: 1.1.0 module: cjs",serverType:"ws"},ro={},eo=function(t){var r=t.toLowerCase();return r.indexOf("http")>-1?r.indexOf("https")>-1?r.replace("https","wss"):r.replace("http","ws"):r};function no(t,r){return void 0===r&&(r=!1),!1===r?function(r){return new t(eo(r))}:function(r,e){var n=eo(r),o=e&&"string"==typeof e?n+"?token="+e:n;try{return new t(o)}catch(t){return console.error("WebSocket Connection Error",t),!1}}}function oo(t,r){var e=r.hostname,n=r.wssPath,o=r.wsOptions;return(0,r.nspClient)(t?[e,t].join("/"):n,o)}var ao=function(t,r,e){var n=e.useCallbackStyle,o=e.log,a=n?"error":"onError",i=n?"result":"onResult";r.$only(hn(t,"emit"),(function(e,n){o("[notLoginHandler] hijack the ws call",t,e,n);var u={message:"NOT LOGIN"};r.$call(hn(t,e,a),[u]),r.$call(hn(t,e,i),[{error:u}])}))};function io(t,r,e,n,o,a){var i=function(t){return t.length>1&&t[0]}(o),u=!1,c=t.log;o.forEach((function(o){if(u=i===o,a[o]){c("[call bindWsHandler]",u,o);var s=[o,a[o],e,u,t];if("socket.io"===t.serverType){var f=r.nspSet;s.push(f[o])}Reflect.apply(n,null,s)}else ao(o,e,t)})),e.$on("__logout__",(function(){c("LOGOUT_EVENT_NAME"),function(t,r,e,n){void 0===n&&(n={});var o=n.useCallbackStyle?"error":"onError";r.forEach((function(r){t.$call(hn(r,o),[{message:e,namespace:r}])}))}(e,o,"__logout__"),o.forEach((function(r){Tn(e,r),a[r]=!1,ao(r,e,t)}))}))}var uo=["__reply__","__event__","__data__"],co=function(t){var r,e=t.data;if(!1!==(r=function(t){var r=t.data;return!!r&&(uo.filter((function(t){return pn(r,t)})).length===uo.length&&r)}(un(e)?JSON.parse(e):e)))return{resolverName:r.__event__,data:r.__data__,type:r.__reply__};throw new h("payload can not be decoded",t)},so=function(t,r,e,n,o){var a=[r];e&&a.push(e),a.push(o);var i=Reflect.apply(hn,null,a),u=n.data||n;t.$trigger(i,[u])};function fo(t,r,e,n,o){var a=o.useCallbackStyle,i=o.log;i("wsMainHandler log test");var u=a?"ready":"onReady",c=a?"login":"onLogin",s=a?"message":"onMessage",f=a?"result":"onResult",l=a?"error":"onError";r.onopen=function(){i("ws.onopen listened"),e.$call(u,t),n&&(i("isPrivate and fire the "+c),e.$call(c,t)),e.$only(hn(t,"emit"),(function(t,e){i("calling server",t,e),r.send(function(t,r,e){return void 0===r&&(r=[]),void 0===e&&(e=!1),JSON.stringify(wn(t,r,e))}(t,e))}))},r.onmessage=function(r){try{var n=co(r),o=n.resolverName,a=n.type;switch(i("Hear from server",a,n),a){case"emit":var u=hn(t,o,s),c=e.$trigger(u,[n]);i("EMIT_REPLY_TYPE",u,c);break;case"acknowledge":var p=hn(t,o,f);e.$trigger(p,[n]);break;case"error":i("ERROR_TYPE"),so(e,t,o,n,l);break;default:i("Unhandled event!",n),so(e,t,o,n,l)}}catch(r){console.error("ws.onmessage error",r),so(e,t,!1,r,l)}},r.onclose=function(){i("ws.onclose callback")},e.$on("__logout__",(function(){try{i("terminate ws connection"),r.terminate()}catch(t){console.error("ws.terminate error",t)}}))}var lo=function(t,r,e){var n,o=r.nspSet,a=r.publicNamespace,i=!1,u=[],c={};if(t.enableAuth)i=!0,c=(u=function(t,r){var e=[];for(var n in t)n===r?e[1]=n:e[0]=n;return e}(o,a)).map((function(r,n){var o,a,i;return 0===n?e?(t.token=e,(o={})[r]=function(t,r){var e=r.hostname,n=r.wssPath,o=r.token,a=r.wsOptions,i=r.nspAuthClient,u=t?[e,t].join("/"):n;if(o&&"string"!=typeof o)throw new Error("Expect token to be string, but got "+o);return i(u,o,a)}(r,t),o):((a={})[r]=!1,a):((i={})[r]=oo(r,t),i)})).reduce((function(t,r){return Object.assign(t,r)}),{});else{var s=(n=o,Object.keys(n)[0]);u.push(s),c[s]=oo(!1,t)}return{nsps:c,namespaces:u,login:i}};var po,ho,vo,go=(ho=no(po=r),vo=no(po,!0),function(t,r,e){t.nspClient=ho,t.nspAuthClient=vo;var n=t.log;return n&&"function"==typeof n&&(n("@jsonql/ws ee",e.name),n("@jsonql/ws createClientResolver",t)),function(t,r,e){var n=[t,r,e,fo],o=t.token,a=t.log,i=lo(t,r,o),u=i.nsps,c=i.namespaces,s=i.login;return Reflect.apply(io,null,n.concat([c,u])),s&&e.$only("__login__",(function(o){a("createClient LOGIN_EVENT_NAME"),Tn(e,c);var i=lo(t,r,o);Reflect.apply(io,null,n.concat([i.namespaces,i.nsps]))})),{opts:t,nspMap:r,ee:e}}(t,r,e)});module.exports=function(t,r){return void 0===t&&(t={}),void 0===r&&(r={}),Zn(go,ro,Object.assign(to,r))(t)}; +'use strict'; + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var WebSocket = _interopDefault(require('ws')); + +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; + +/** + * 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; +} + +/** + * 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 = Array.isArray; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * 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(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; +} + +/** Used for built-in method references. */ +var objectProto$1 = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString$1 = objectProto$1.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(value) { + return nativeObjectToString$1.call(value); +} + +/** `Object#toString` result references. */ +var nullTag = '[object Null]', + undefinedTag = '[object Undefined]'; + +/** Built-in value references. */ +var symToStringTag$1 = Symbol ? Symbol.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(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag$1 && symToStringTag$1 in Object(value)) + ? getRawTag(value) + : objectToString(value); +} + +/** + * 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 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return value != null && typeof value == 'object'; +} + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && baseGetTag(value) == symbolTag); +} + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + +/** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +/** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ +function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; +} + +/** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ +function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); +} + +/** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; +} + +/** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ +function baseIsNaN(value) { + return value !== value; +} + +/** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; +} + +/** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseIndexOf(array, value, fromIndex) { + return value === value + ? strictIndexOf(array, value, fromIndex) + : baseFindIndex(array, baseIsNaN, fromIndex); +} + +/** + * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the last unmatched string symbol. + */ +function charsEndIndex(strSymbols, chrSymbols) { + var index = strSymbols.length; + + while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; +} + +/** + * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the first unmatched string symbol. + */ +function charsStartIndex(strSymbols, chrSymbols) { + var index = -1, + length = strSymbols.length; + + while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; +} + +/** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function asciiToArray(string) { + return string.split(''); +} + +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f', + reComboHalfMarksRange = '\\ufe20-\\ufe2f', + rsComboSymbolsRange = '\\u20d0-\\u20ff', + rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, + rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsZWJ = '\\u200d'; + +/** 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/). */ +var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + +/** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ +function hasUnicode(string) { + return reHasUnicode.test(string); +} + +/** Used to compose unicode character classes. */ +var rsAstralRange$1 = '\\ud800-\\udfff', + rsComboMarksRange$1 = '\\u0300-\\u036f', + reComboHalfMarksRange$1 = '\\ufe20-\\ufe2f', + rsComboSymbolsRange$1 = '\\u20d0-\\u20ff', + rsComboRange$1 = rsComboMarksRange$1 + reComboHalfMarksRange$1 + rsComboSymbolsRange$1, + rsVarRange$1 = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsAstral = '[' + rsAstralRange$1 + ']', + rsCombo = '[' + rsComboRange$1 + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange$1 + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsZWJ$1 = '\\u200d'; + +/** Used to compose unicode regexes. */ +var reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange$1 + ']?', + rsOptJoin = '(?:' + rsZWJ$1 + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + +/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ +var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + +/** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function unicodeToArray(string) { + return string.match(reUnicode) || []; +} + +/** + * Converts `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function stringToArray(string) { + return hasUnicode(string) + ? unicodeToArray(string) + : asciiToArray(string); +} + +/** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ +function toString(value) { + return value == null ? '' : baseToString(value); +} + +/** Used to match leading and trailing whitespace. */ +var reTrim = /^\s+|\s+$/g; + +/** + * Removes leading and trailing whitespace or specified characters from `string`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {string} Returns the trimmed string. + * @example + * + * _.trim(' abc '); + * // => 'abc' + * + * _.trim('-_-abc-_-', '_-'); + * // => 'abc' + * + * _.map([' foo ', ' bar '], _.trim); + * // => ['foo', 'bar'] + */ +function trim(string, chars, guard) { + string = toString(string); + if (string && (guard || chars === undefined)) { + return string.replace(reTrim, ''); + } + if (!string || !(chars = baseToString(chars))) { + return string; + } + var strSymbols = stringToArray(string), + chrSymbols = stringToArray(chars), + start = charsStartIndex(strSymbols, chrSymbols), + end = charsEndIndex(strSymbols, chrSymbols) + 1; + + return castSlice(strSymbols, start, end).join(''); +} + +/** + * Check several parameter that there is something in the param + * @param {*} param input + * @return {boolean} + */ + var isNotEmpty = function (a) { + if (isArray(a)) { + return true; + } + return a !== undefined && a !== null && trim(a) !== ''; +}; + +/** `Object#toString` result references. */ +var numberTag = '[object Number]'; + +/** + * 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 + * + * _.isNumber('3'); + * // => false + */ +function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && baseGetTag(value) == numberTag); +} + +/** + * 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 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ +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; +} + +/** `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 + * + * _.isString(1); + * // => false + */ +function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); +} + +// 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) ) +}; + +// validate string type +/** + * @param {string} value expected value + * @return {boolean} true if OK + */ +var checkIsString = function(value) { + return (trim(value) !== '') ? isString(value) : false; +}; + +// check for boolean + +/** + * @param {boolean} value expected + * @return {boolean} true if OK + */ +var checkIsBoolean = function(value) { + return value !== null && value !== undefined && typeof value === 'boolean' +}; + +// validate any thing only check if there is something + +/** + * @param {*} value the value + * @param {boolean} [checkNull=true] strict check if there is null value + * @return {boolean} true is OK + */ +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; +}; + +// 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'; +// for contract-cli +var KEY_WORD = 'continue'; + +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 LOGIN_NAME = 'login'; +var ISSUER_NAME = LOGIN_NAME; // legacy issue need to replace them later +var LOGOUT_NAME = 'logout'; + +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 = '>'; + +var NO_ERROR_MSG = 'No message'; +var NO_STATUS_CODE = -1; +var LOGIN_EVENT_NAME = '__login__'; +var LOGOUT_EVENT_NAME = '__logout__'; +var EMIT_REPLY_TYPE = 'emit'; + +var NSP_SET = 'nspSet'; +var PUBLIC_NAMESPACE = 'publicNamespace'; +var JS_WS_NAME = 'ws'; + +// for ws client +var ON_MESSAGE_PROP_NAME = 'onMessage'; +var ON_RESULT_PROP_NAME = 'onResult'; +var ON_ERROR_PROP_NAME = 'onError'; +var ON_READY_PROP_NAME = 'onReady'; +var ON_LOGIN_PROP_NAME = 'onLogin'; // new @1.8.6 + +var SEND_MSG_PROP_NAME = 'send'; +var IO_ROUNDTRIP_LOGIN = 'roundtip'; +var IO_HANDSHAKE_LOGIN = 'handshake'; + +// 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!'; +// @TODO the jsdoc return array. and we should also allow array syntax +var DEFAULT_TYPE$1 = DEFAULT_TYPE; +var ARRAY_TYPE_LFT$1 = ARRAY_TYPE_LFT; +var ARRAY_TYPE_RGT$1 = ARRAY_TYPE_RGT; + +var TYPE_KEY$1 = TYPE_KEY; +var OPTIONAL_KEY$1 = OPTIONAL_KEY; +var ENUM_KEY$1 = ENUM_KEY; +var ARGS_KEY$1 = ARGS_KEY; +var CHECKER_KEY$1 = CHECKER_KEY; +var ALIAS_KEY$1 = ALIAS_KEY; + +var ARRAY_TYPE$1 = ARRAY_TYPE; +var OBJECT_TYPE$1 = OBJECT_TYPE; +var STRING_TYPE$1 = STRING_TYPE; +var BOOLEAN_TYPE$1 = BOOLEAN_TYPE; +var NUMBER_TYPE$1 = NUMBER_TYPE; +var KEY_WORD$1 = KEY_WORD; +var OR_SEPERATOR$1 = OR_SEPERATOR; + +// not actually in use +// export const NUMBER_TYPES = JSONQL_CONSTANTS.NUMBER_TYPES; + +// primitive types + +/** + * 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 + */ +var combineFn = function(type) { + switch (type) { + case NUMBER_TYPE$1: + return checkIsNumber; + case STRING_TYPE$1: + return checkIsString; + case BOOLEAN_TYPE$1: + return checkIsBoolean; + default: + return checkIsAny; + } +}; + +// validate array type + +/** + * @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 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 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) > -1 && type.indexOf(ARRAY_TYPE_RGT$1) > -1) { + var _type = type.replace(ARRAY_TYPE_LFT$1, '').replace(ARRAY_TYPE_RGT$1, ''); + if (_type.indexOf(OR_SEPERATOR$1)) { + return _type.split(OR_SEPERATOR$1) + } + return [_type] + } + return false; +}; + +/** + * 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 + */ +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; +}; + +/** + * 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); + +/** `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 `_.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 = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; +} + +/** + * 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(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 = createBaseFor(); + +/** + * 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(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} + +/** `Object#toString` result references. */ +var argsTag = '[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(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; +} + +/** Used for built-in method references. */ +var objectProto$3 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$2 = objectProto$3.hasOwnProperty; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto$3.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$2.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); +}; + +/** + * 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; +} + +/** Detect free variable `exports`. */ +var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + +/** 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; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeIsBuffer = Buffer ? Buffer.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 = nativeIsBuffer || stubFalse; + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** Used to detect unsigned integer values. */ +var reIsUint = /^(?: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(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); +} + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER$1 = 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(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER$1; +} + +/** `Object#toString` result references. */ +var argsTag$1 = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[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] = +typedArrayTags[mapTag] = typedArrayTags[numberTag$1] = +typedArrayTags[objectTag$1] = typedArrayTags[regexpTag] = +typedArrayTags[setTag] = typedArrayTags[stringTag$1] = +typedArrayTags[weakMapTag] = 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(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(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(func) { + return function(value) { + return func(value); + }; +} + +/** 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; + +/** Detect free variable `process` from Node.js. */ +var freeProcess = moduleExports$1 && freeGlobal.process; + +/** Used to access faster Node.js helpers. */ +var nodeUtil = (function() { + try { + // Use `util.types` for Node.js 10+. + var types = freeModule$1 && freeModule$1.require && freeModule$1.require('util').types; + + 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; + +/** + * 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 = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + +/** Used for built-in method references. */ +var objectProto$4 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$3 = objectProto$4.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(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$3.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; +} + +/** Used for built-in method references. */ +var objectProto$5 = 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$5; + + return value === proto; +} + +/* 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$6 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$4 = objectProto$6.hasOwnProperty; + +/** + * 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 baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty$4.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; +} + +/** + * 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(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); +} + +/** `Object#toString` result references. */ +var asyncTag = '[object AsyncFunction]', + funcTag$1 = '[object Function]', + genTag = '[object GeneratorFunction]', + proxyTag = '[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(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$1 || tag == genTag || tag == asyncTag || tag == proxyTag; +} + +/** + * 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$1(value) { + return value != null && isLength(value.length) && !isFunction(value); +} + +/** + * 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); +} + +/** + * 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); +} + +/** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ +function listCacheClear() { + this.__data__ = []; + this.size = 0; +} + +/** + * 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(value, other) { + return value === other || (value !== value && other !== other); +} + +/** + * 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(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; +} + +/** 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. + * + * @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(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; +} + +/** + * 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. + */ +function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(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(key) { + return assocIndexOf(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(key, value) { + var data = this.__data__, + index = assocIndexOf(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(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.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. + * + * @private + * @name clear + * @memberOf Stack + */ +function stackClear() { + this.__data__ = new ListCache; + 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(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(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(key) { + return this.__data__.has(key); +} + +/** Used to detect overreaching core-js shims. */ +var coreJsData = root['__core-js_shared__']; + +/** 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) : ''; +}()); + +/** + * 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(func) { + return !!maskSrcKey && (maskSrcKey in func); +} + +/** Used for built-in method references. */ +var funcProto$1 = Function.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString$1 = funcProto$1.toString; + +/** + * 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 ''; +} + +/** + * 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$7 = 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$5 = objectProto$7.hasOwnProperty; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + funcToString$2.call(hasOwnProperty$5).replace(reRegExpChar, '\\$&') + .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(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(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(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(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'); + +/* Built-in method references that are verified to be native. */ +var nativeCreate = getNative(Object, 'create'); + +/** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ +function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(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(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 = '__lodash_hash_undefined__'; + +/** Used for built-in method references. */ +var objectProto$8 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$6 = objectProto$8.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(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty$6.call(data, key) ? data[key] : undefined; +} + +/** Used for built-in method references. */ +var objectProto$9 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$7 = objectProto$9.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(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty$7.call(data, key); +} + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED$1 = '__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(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. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +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]); + } +} + +// 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. + * + * @private + * @name clear + * @memberOf MapCache + */ +function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map$1 || ListCache), + 'string': new Hash + }; +} + +/** + * 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(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(map, key) { + var data = map.__data__; + return isKeyable(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(key) { + var result = getMapData(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(key) { + return getMapData(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(key) { + return getMapData(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(key, value) { + var data = getMapData(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(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.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 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. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +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; + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED$2 = '__lodash_hash_undefined__'; + +/** + * 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; +} + +/** + * 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); +} + +/** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ +function SetCache(values) { + var index = -1, + length = values == null ? 0 : values.length; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } +} + +// Add methods to `SetCache`. +SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; +SetCache.prototype.has = setCacheHas; + +/** + * 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; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; +} + +/** + * 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`. + */ +function cacheHas(cache, key) { + return cache.has(key); +} + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** + * 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; + + 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; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + 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; +} + +/** Built-in value references. */ +var Uint8Array = root.Uint8Array; + +/** + * 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); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; +} + +/** + * 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); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; +} + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG$1 = 1, + COMPARE_UNORDERED_FLAG$1 = 2; + +/** `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]'; + +var arrayBufferTag$1 = '[object ArrayBuffer]', + dataViewTag$1 = '[object DataView]'; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto$1 = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto$1 ? symbolProto$1.valueOf : undefined; + +/** + * 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; + + case arrayBufferTag$1: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + + 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); + + case errorTag$1: + return object.name == other.name && object.message == other.message; + + 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 + ''); + + case mapTag$1: + var convert = mapToArray; + + case setTag$1: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG$1; + convert || (convert = setToArray); + + 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; + + // 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; + + case symbolTag$1: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + 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; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; +} + +/** + * 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)); +} + +/** + * 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 []; +} + +/** Used for built-in method references. */ +var objectProto$a = Object.prototype; + +/** Built-in value references. */ +var propertyIsEnumerable$1 = objectProto$a.propertyIsEnumerable; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetSymbols = Object.getOwnPropertySymbols; + +/** + * 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); + }); +}; + +/** + * 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); +} + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG$2 = 1; + +/** Used for built-in method references. */ +var objectProto$b = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$8 = objectProto$b.hasOwnProperty; + +/** + * 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; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty$8.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); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + 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; + + // 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; +} + +/* Built-in method references that are verified to be native. */ +var DataView = getNative(root, 'DataView'); + +/* Built-in method references that are verified to be native. */ +var Promise$1 = getNative(root, 'Promise'); + +/* Built-in method references that are verified to be native. */ +var Set$1 = getNative(root, 'Set'); + +/* Built-in method references that are verified to be native. */ +var WeakMap$1 = getNative(root, 'WeakMap'); + +/** `Object#toString` result references. */ +var mapTag$2 = '[object Map]', + objectTag$2 = '[object Object]', + promiseTag = '[object Promise]', + setTag$2 = '[object Set]', + weakMapTag$1 = '[object WeakMap]'; + +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); + +/** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +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; + }; +} + +var getTag$1 = getTag; + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG$3 = 1; + +/** `Object#toString` result references. */ +var argsTag$2 = '[object Arguments]', + arrayTag$1 = '[object Array]', + objectTag$3 = '[object Object]'; + +/** Used for built-in method references. */ +var objectProto$c = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$9 = objectProto$c.hasOwnProperty; + +/** + * 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`. + */ +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); + + 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; + } + 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$9.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty$9.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + 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); +} + +/** + * 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); +} + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG$4 = 1, + COMPARE_UNORDERED_FLAG$2 = 2; + +/** + * 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; + + 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]; + + 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; +} + +/** + * 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); +} + +/** + * 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; + + while (length--) { + var key = result[length], + value = object[key]; + + result[length] = [key, value, isStrictComparable(value)]; + } + return result; +} + +/** + * 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. + */ +function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + return false; + } + return object[key] === srcValue && + (srcValue !== undefined || (key in Object(object))); + }; +} + +/** + * 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. + */ +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); + }; +} + +/** Used to match property names within property paths. */ +var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/; + +/** + * 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`. + */ +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'; + +/** + * 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; + */ +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; +} + +// Expose `MapCache`. +memoize.Cache = MapCache; + +/** Used as the maximum memoize cache size. */ +var MAX_MEMOIZE_SIZE = 500; + +/** + * 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(); + } + return key; + }); + + var cache = result.cache; + return result; +} + +/** Used to match property names within property paths. */ +var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + +/** Used to match backslashes in property paths. */ +var reEscapeChar = /\\(\\)?/g; + +/** + * 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; +}); + +/** + * 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)); +} + +/** Used as references for various `Number` constants. */ +var INFINITY$1 = 1 / 0; + +/** + * 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; +} + +/** + * 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); + }; +} + +/** + * 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(value) { + return value; +} + +/** + * 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); +} + +// 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; + + 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; +}; + +/** + * fold this into it's own function to handler different object type + * @param {object} p the prepared object for process + * @return {boolean} + */ +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) +}; + +/** + * 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? + */ +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; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, Jsonql406Error); + } + } + + 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 406; + }; + + staticAccessors.name.get = function () { + return 'Jsonql406Error'; + }; + + Object.defineProperties( Jsonql406Error, staticAccessors ); + + return Jsonql406Error; +}(Error)); + +/** + * 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? + */ +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; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, Jsonql500Error); + } + } + + 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 500; + }; + + staticAccessors.name.get = function () { + return 'Jsonql500Error'; + }; + + Object.defineProperties( Jsonql500Error, staticAccessors ); + + return Jsonql500Error; +}(Error)); + +/** + * 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? + */ +var JsonqlForbiddenError = /*@__PURE__*/(function (Error) { + function JsonqlForbiddenError() { + 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 = JsonqlForbiddenError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlForbiddenError); + } + } + + if ( Error ) JsonqlForbiddenError.__proto__ = Error; + JsonqlForbiddenError.prototype = Object.create( Error && Error.prototype ); + JsonqlForbiddenError.prototype.constructor = JsonqlForbiddenError; + + var staticAccessors = { statusCode: { configurable: true },name: { configurable: true } }; + + staticAccessors.statusCode.get = function () { + return 403; + }; + + staticAccessors.name.get = function () { + return 'JsonqlForbiddenError'; + }; + + Object.defineProperties( JsonqlForbiddenError, staticAccessors ); + + return JsonqlForbiddenError; +}(Error)); + +/** + * 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? + */ +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); + } + } + + 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 401; + }; + + staticAccessors.name.get = function () { + return 'JsonqlAuthorisationError'; + }; + + Object.defineProperties( JsonqlAuthorisationError, staticAccessors ); + + return JsonqlAuthorisationError; +}(Error)); + +/** + * 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? + */ +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]; + + this.className = JsonqlContractAuthError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlContractAuthError); + } + } + + 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 401; + }; + + staticAccessors.name.get = function () { + return 'JsonqlContractAuthError'; + }; + + Object.defineProperties( JsonqlContractAuthError, staticAccessors ); + + return JsonqlContractAuthError; +}(Error)); + +/** + * 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? + */ +var JsonqlResolverAppError = /*@__PURE__*/(function (Error) { + function JsonqlResolverAppError() { + 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 = JsonqlResolverAppError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlResolverAppError); + } + } + + 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 500; + }; + + staticAccessors.name.get = function () { + return 'JsonqlResolverAppError'; + }; + + Object.defineProperties( JsonqlResolverAppError, staticAccessors ); + + return JsonqlResolverAppError; +}(Error)); + +/** + * 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? + */ +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; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlResolverNotFoundError); + } + } + + 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 404; + }; + + staticAccessors.name.get = function () { + return 'JsonqlResolverNotFoundError'; + }; + + Object.defineProperties( JsonqlResolverNotFoundError, staticAccessors ); + + return JsonqlResolverNotFoundError; +}(Error)); + +// 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); + } + } + + 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 ( 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 ( 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)); + +// 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); + + this.message = args[0]; + this.detail = args[1]; + + this.className = JsonqlValidationError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlValidationError); + } + } + + if ( Error ) JsonqlValidationError.__proto__ = Error; + JsonqlValidationError.prototype = Object.create( Error && Error.prototype ); + JsonqlValidationError.prototype.constructor = JsonqlValidationError; + + var staticAccessors = { name: { configurable: true } }; + + staticAccessors.name.get = function () { + return 'JsonqlValidationError'; + }; + + Object.defineProperties( JsonqlValidationError, staticAccessors ); + + return JsonqlValidationError; +}(Error)); + +/** + * 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 = /*@__PURE__*/(function (Error) { + function JsonqlError() { + 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 = JsonqlError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlError); + // this.detail = this.stack; + } + } + + if ( Error ) JsonqlError.__proto__ = Error; + JsonqlError.prototype = Object.create( Error && Error.prototype ); + JsonqlError.prototype.constructor = JsonqlError; + + var staticAccessors = { name: { configurable: true },statusCode: { configurable: true } }; + + staticAccessors.name.get = function () { + return 'JsonqlError'; + }; + + staticAccessors.statusCode.get = function () { + return NO_STATUS_CODE; + }; + + Object.defineProperties( JsonqlError, staticAccessors ); + + return JsonqlError; +}(Error)); + +// 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; + } + + if ( Error ) JsonqlServerError.__proto__ = Error; + JsonqlServerError.prototype = Object.create( Error && Error.prototype ); + JsonqlServerError.prototype.constructor = JsonqlServerError; + + var staticAccessors = { name: { configurable: true } }; + + staticAccessors.name.get = function () { + return 'JsonqlServerError'; + }; + + 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 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(msg, detail) + } +} + +// 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 + +/** + * 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 + */ +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; +}; + +/** + * actually picking the validator + * @param {*} type for checking + * @param {*} value for checking + * @return {boolean} true on OK + */ +var validateHandler = function(type, value) { + var tmp; + switch (true) { + case type === OBJECT_TYPE$1: + // debugFn('call OBJECT_TYPE') + return !objectTypeHandler(value) + case type === ARRAY_TYPE$1: + // 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) + } +}; + +/** + * 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 + */ +var getOptionalValue = function(arg, param) { + if (arg !== undefined) { + return arg; + } + return (param.optional === true && param.defaultvalue !== undefined ? param.defaultvalue : null) +}; + +/** + * 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 + */ +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 JsonqlError(PARAMS_NOT_ARRAY_ERR) + } + if (params.length === 0) { + return []; + } + if (!checkIsArray(args)) { + throw new JsonqlError(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$1 ]; + // 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(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([]) + }) +}; + +var defineProperty = (function() { + try { + var func = getNative(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(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(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(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, 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; + +/** Built-in value references. */ +var Buffer$1 = moduleExports$2 ? root.Buffer : undefined, + allocUnsafe = Buffer$1 ? Buffer$1.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(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; +} + +/** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ +function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(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(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]; + } + return array; +} + +/** 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; + }; +}()); + +/** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ +function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; +} + +/** + * 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(value) { + return isObjectLike(value) && isArrayLike$1(value); +} + +/** + * 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(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$d = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$a = objectProto$d.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(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty$a.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(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(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(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; +} + +/** + * 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(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$e = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$b = objectProto$e.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(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty$b.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(object) { + return isArrayLike$1(object) ? arrayLikeKeys(object, true) : baseKeysIn(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(value) { + return copyObject(value, keysIn(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(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); +} + +/** + * 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; + + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); +} + +/** + * 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]); + } + return func.apply(thisArg, args); +} + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = 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(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); + + 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); + }; +} + +/** + * 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; + }; +} + +/** + * 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; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeNow = Date.now; + +/** + * 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. + */ +function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; +} + +/** + * 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); + +/** + * 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 + ''); +} + +/** + * 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; +} + +/** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ +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; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + 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; + }); +} + +/** + * 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); +}); + +/** + * 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 = 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$1]; } ); + 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(_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 + } +} + +/** + * 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$1] === true && isEmpty(config[key])) + ? merge({}, value, ( obj = {}, obj[KEY_WORD$1] = true, obj )) + : ( obj$1 = {}, obj$1[ARGS_KEY$1] = config[key], obj$1[TYPE_KEY$1] = value[TYPE_KEY$1], obj$1[OPTIONAL_KEY$1] = value[OPTIONAL_KEY$1] || false, obj$1[ENUM_KEY$1] = value[ENUM_KEY$1] || false, obj$1[CHECKER_KEY$1] = value[CHECKER_KEY$1] || 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 = 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 = 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$1] ], + [( obj = {}, obj[TYPE_KEY$1] = toArray(value[TYPE_KEY$1]), obj[OPTIONAL_KEY$1] = value[OPTIONAL_KEY$1], 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; +}; + +/** + * 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$1]) { + return value[ARGS_KEY$1] + } + var check = validateHandler$1(value, cb); + if (check.length) { + // log('runValidationAction', key, value) + throw new JsonqlTypeError(key, check) + } + if (value[ENUM_KEY$1] !== false && !enumHandler(value[ARGS_KEY$1], value[ENUM_KEY$1])) { + // log(ENUM_KEY, value[ENUM_KEY]) + throw new JsonqlEnumError(key) + } + if (value[CHECKER_KEY$1] !== false && !checkerHandler(value[ARGS_KEY$1], value[CHECKER_KEY$1])) { + // log(CHECKER_KEY, value[CHECKER_KEY]) + throw new JsonqlCheckerError(key) + } + return value[ARGS_KEY$1] + } +} + +/** + * @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 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) { + /** + * 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= {}; + + 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 +/** + * @TODO remove this implmenetation once the test is done + */ +var dummyLogger = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + Reflect.apply(console.info, console, ['[jsonql-ws-client-core]' ].concat( args)); +}; + +/** + * 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') { + opts.log = dummyLogger; + } + opts.log('--- wsClientCore config opts ---', opts); + return opts +}; + +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) +} +// wrapper to make sure it string +function hashCode2Str(s) { + return hashCode(s) + '' +} + +// making all the functionality on it's own +// import { WatchClass } from './watch' + +var SuspendClass = function SuspendClass() { + // suspend, release and queue + this.__suspend__ = null; + this.queueStore = new Set(); + /* + this.watch('suspend', function(value, prop, oldValue) { + this.logger(`${prop} set from ${oldValue} to ${value}`) + // it means it set the suspend = true then release it + if (oldValue === true && value === false) { + // we want this happen after the return happens + setTimeout(() => { + this.release() + }, 1) + } + return value; // we need to return the value to store it + }) + */ +}; + +var prototypeAccessors = { $suspend: { configurable: true },$queues: { configurable: true } }; + +/** + * setter to set the suspend and check if it's boolean value + * @param {boolean} value to trigger + */ +prototypeAccessors.$suspend.set = function (value) { + var this$1 = this; + + if (typeof value === 'boolean') { + var lastValue = this.__suspend__; + this.__suspend__ = value; + this.logger('($suspend)', ("Change from " + lastValue + " --> " + value)); + if (lastValue === true && value === false) { + setTimeout(function () { + this$1.release(); + }, 1); + } + } else { + throw new Error("$suspend only accept Boolean value!") + } +}; + +/** + * queuing call up when it's in suspend mode + * @param {any} value + * @return {Boolean} true when added or false when it's not + */ +SuspendClass.prototype.$queue = function $queue () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (this.__suspend__ === true) { + this.logger('($queue)', 'added to $queue', args); + // there shouldn't be any duplicate ... + this.queueStore.add(args); + } + return this.__suspend__; +}; + +/** + * 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 [] +}; + +/** + * Release the queue + * @return {int} size if any + */ +SuspendClass.prototype.release = function release () { + var this$1 = this; + + var size = this.queueStore.size; + this.logger('(release)', ("Release was called " + size)); + if (size > 0) { + var queue = Array.from(this.queueStore); + this.queueStore.clear(); + this.logger('queue', queue); + queue.forEach(function (args) { + this$1.logger(args); + Reflect.apply(this$1.$trigger, this$1, args); + }); + this.logger(("Release size " + (this.queueStore.size))); + } +}; + +Object.defineProperties( SuspendClass.prototype, prototypeAccessors ); + +// break up the main file because its getting way too long + +var NbEventServiceBase = /*@__PURE__*/(function (SuspendClass) { + function NbEventServiceBase(config) { + if ( config === void 0 ) 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 ( SuspendClass ) NbEventServiceBase.__proto__ = SuspendClass; + NbEventServiceBase.prototype = Object.create( SuspendClass && SuspendClass.prototype ); + NbEventServiceBase.prototype.constructor = NbEventServiceBase; + + var prototypeAccessors = { is: { configurable: true },normalStore: { configurable: true },lazyStore: { configurable: true } }; + + // for id if the instance is this class + prototypeAccessors.is.get = function () { + return 'nb-event-service' + }; + + /** + * validate the event name(s) + * @param {string[]} evt event name + * @return {boolean} true when OK + */ + NbEventServiceBase.prototype.validateEvt = function validateEvt () { + var this$1 = this; + var evt = [], len = arguments.length; + while ( len-- ) evt[ len ] = arguments[ len ]; + + evt.forEach(function (e) { + if (typeof e !== 'string') { + this$1.logger('(validateEvt)', e); + throw new Error("event name must be string type!") + } + }); + return true; + }; + + /** + * Simple quick check on the two main parameters + * @param {string} evt event name + * @param {function} callback function to call + * @return {boolean} true when OK + */ + NbEventServiceBase.prototype.validate = function validate (evt, callback) { + if (this.validateEvt(evt)) { + if (typeof callback === 'function') { + return true; + } + } + throw new Error("callback required to be function type!") + }; + + /** + * Check if this type is correct or not added in V1.5.0 + * @param {string} type for checking + * @return {boolean} true on OK + */ + NbEventServiceBase.prototype.validateType = function validateType (type) { + var types = ['on', 'only', 'once', 'onlyOnce']; + return !!types.filter(function (t) { return type === t; }).length; + }; + + /** + * Run the callback + * @param {function} callback function to execute + * @param {array} payload for callback + * @param {object} ctx context or null + * @return {void} the result store in $done + */ + NbEventServiceBase.prototype.run = function run (callback, payload, ctx) { + this.logger('(run)', callback, payload, ctx); + this.$done = Reflect.apply(callback, ctx, this.toArray(payload)); + }; + + /** + * Take the content out and remove it from store id by the name + * @param {string} evt event name + * @param {string} [storeName = lazyStore] name of store + * @return {object|boolean} content or false on not found + */ + NbEventServiceBase.prototype.takeFromStore = function takeFromStore (evt, storeName) { + if ( storeName === void 0 ) storeName = 'lazyStore'; + + var store = this[storeName]; // it could be empty at this point + if (store) { + this.logger('(takeFromStore)', storeName, store); + if (store.has(evt)) { + var content = store.get(evt); + this.logger('(takeFromStore)', ("has " + evt), content); + store.delete(evt); + return content; + } + return false; + } + throw new Error((storeName + " is not supported!")) + }; + + /** + * The add to store step is similar so make it generic for resuse + * @param {object} store which store to use + * @param {string} evt event name + * @param {spread} args because the lazy store and normal store store different things + * @return {array} store and the size of the store + */ + NbEventServiceBase.prototype.addToStore = function addToStore (store, evt) { + var args = [], len = arguments.length - 2; + while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; + + var fnSet; + if (store.has(evt)) { + this.logger('(addToStore)', (evt + " existed")); + fnSet = store.get(evt); + } else { + this.logger('(addToStore)', ("create new Set for " + evt)); + // this is new + fnSet = new Set(); + } + // lazy only store 2 items - this is not the case in V1.6.0 anymore + // we need to check the first parameter is string or not + if (args.length > 2) { + if (Array.isArray(args[0])) { // lazy store + // check if this type of this event already register in the lazy store + var t = args[2]; + if (!this.checkTypeInLazyStore(evt, t)) { + fnSet.add(args); + } + } 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] + }; + + /** + * @param {array} args for compare + * @param {object} fnSet A Set to search from + * @return {boolean} true on exist + */ + NbEventServiceBase.prototype.checkContentExist = function checkContentExist (args, fnSet) { + var list = Array.from(fnSet); + return !!list.filter(function (l) { + var hash = l[0]; + if (hash === args[0]) { + return true; + } + return false; + }).length; + }; + + /** + * get the existing type to make sure no mix type add to the same store + * @param {string} evtName event name + * @param {string} type the type to check + * @return {boolean} true you can add, false then you can't add this type + */ + NbEventServiceBase.prototype.checkTypeInStore = function checkTypeInStore (evtName, type) { + this.validateEvt(evtName, type); + var all = this.$get(evtName, true); + if (all === false) { + // pristine it means you can add + return true; + } + // it should only have ONE type in ONE event store + return !all.filter(function (list) { + var t = list[3]; + return type !== t; + }).length; + }; + + /** + * This is checking just the lazy store because the structure is different + * therefore we need to use a new method to check it + */ + NbEventServiceBase.prototype.checkTypeInLazyStore = function checkTypeInLazyStore (evtName, type) { + this.validateEvt(evtName, type); + var store = this.lazyStore.get(evtName); + this.logger('(checkTypeInLazyStore)', store); + if (store) { + return !!Array + .from(store) + .filter(function (l) { + var t = l[2]; + return t !== type; + }).length + } + return false; + }; + + /** + * wrapper to re-use the addToStore, + * V1.3.0 add extra check to see if this type can add to this evt + * @param {string} evt event name + * @param {string} type on or once + * @param {function} callback function + * @param {object} context the context the function execute in or null + * @return {number} size of the store + */ + NbEventServiceBase.prototype.addToNormalStore = function addToNormalStore (evt, type, callback, context) { + if ( context === void 0 ) context = null; + + this.logger('(addToNormalStore)', evt, type, 'try to add to normal store'); + // @TODO we need to check the existing store for the type first! + if (this.checkTypeInStore(evt, type)) { + this.logger('(addToNormalStore)', (type + " can add to " + evt + " normal store")); + var key = this.hashFnToKey(callback); + var args = [this.normalStore, evt, key, callback, context, type]; + var ref = Reflect.apply(this.addToStore, this, args); + var _store = ref[0]; + var size = ref[1]; + this.normalStore = _store; + return size; + } + return false; + }; + + /** + * Add to lazy store this get calls when the callback is not register yet + * so we only get a payload object or even nothing + * @param {string} evt event name + * @param {array} payload of arguments or empty if there is none + * @param {object} [context=null] the context the callback execute in + * @param {string} [type=false] register a type so no other type can add to this evt + * @return {number} size of the store + */ + NbEventServiceBase.prototype.addToLazyStore = function addToLazyStore (evt, payload, context, type) { + if ( payload === void 0 ) payload = []; + if ( context === void 0 ) context = null; + if ( type === void 0 ) type = false; + + // this is add in V1.6.0 + // when there is type then we will need to check if this already added in lazy store + // and no other type can add to this lazy store + var args = [this.lazyStore, evt, this.toArray(payload), context]; + if (type) { + args.push(type); + } + var ref = Reflect.apply(this.addToStore, this, args); + var _store = ref[0]; + var size = ref[1]; + this.lazyStore = _store; + return size; + }; + + /** + * make sure we store the argument correctly + * @param {*} arg could be array + * @return {array} make sured + */ + NbEventServiceBase.prototype.toArray = function toArray (arg) { + return Array.isArray(arg) ? arg : [arg]; + }; + + /** + * setter to store the Set in private + * @param {object} obj a Set + */ + prototypeAccessors.normalStore.set = function (obj) { + NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj); + }; + + /** + * @return {object} Set object + */ + prototypeAccessors.normalStore.get = function () { + return NB_EVENT_SERVICE_PRIVATE_STORE.get(this) + }; + + /** + * setter to store the Set in lazy store + * @param {object} obj a Set + */ + prototypeAccessors.lazyStore.set = function (obj) { + NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj); + }; + + /** + * @return {object} the lazy store Set + */ + prototypeAccessors.lazyStore.get = function () { + return NB_EVENT_SERVICE_PRIVATE_LAZY.get(this) + }; + + /** + * generate a hashKey to identify the function call + * The build-in store some how could store the same values! + * @param {function} fn the converted to string function + * @return {string} hashKey + */ + NbEventServiceBase.prototype.hashFnToKey = function hashFnToKey (fn) { + return hashCode2Str(fn.toString()) + }; + + Object.defineProperties( NbEventServiceBase.prototype, prototypeAccessors ); + + return NbEventServiceBase; +}(SuspendClass)); + +// The top level +// export +var EventService = /*@__PURE__*/(function (NbStoreService) { + function EventService(config) { + if ( config === void 0 ) config = {}; + + NbStoreService.call(this, config); + } + + if ( NbStoreService ) EventService.__proto__ = NbStoreService; + EventService.prototype = Object.create( NbStoreService && NbStoreService.prototype ); + EventService.prototype.constructor = EventService; + + var prototypeAccessors = { $done: { configurable: true } }; + + /** + * logger function for overwrite + */ + EventService.prototype.logger = function logger () {}; + + ////////////////////////// + // PUBLIC METHODS // + ////////////////////////// + + /** + * Register your evt handler, note we don't check the type here, + * we expect you to be sensible and know what you are doing. + * @param {string} evt name of event + * @param {function} callback bind method --> if it's array or not + * @param {object} [context=null] to execute this call in + * @return {number} the size of the store + */ + EventService.prototype.$on = function $on (evt , callback , context) { + var this$1 = this; + if ( context === void 0 ) context = null; + + var type = 'on'; + this.validate(evt, callback); + // first need to check if this evt is in lazy store + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register first then call later + if (lazyStoreContent === false) { + this.logger('($on)', (evt + " callback is not in lazy store")); + // @TODO we need to check if there was other listener to this + // event and are they the same type then we could solve that + // register the different type to the same event name + + return this.addToNormalStore(evt, type, callback, context) + } + this.logger('($on)', (evt + " found in lazy store")); + // this is when they call $trigger before register this callback + var size = 0; + lazyStoreContent.forEach(function (content) { + var payload = content[0]; + var ctx = content[1]; + var t = content[2]; + if (t && t !== type) { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this$1.logger("($on)", ("call run on " + evt)); + this$1.run(callback, payload, context || ctx); + size += this$1.addToNormalStore(evt, type, callback, context || ctx); + }); + return size; + }; + + /** + * once only registered it once, there is no overwrite option here + * @NOTE change in v1.3.0 $once can add multiple listeners + * but once the event fired, it will remove this event (see $only) + * @param {string} evt name + * @param {function} callback to execute + * @param {object} [context=null] the handler execute in + * @return {boolean} result + */ + EventService.prototype.$once = function $once (evt , callback , context) { + if ( context === void 0 ) context = null; + + this.validate(evt, callback); + var type = 'once'; + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register before call $trigger + var nStore = this.normalStore; + if (lazyStoreContent === false) { + this.logger('($once)', (evt + " not in the lazy store")); + // v1.3.0 $once now allow to add multiple listeners + return this.addToNormalStore(evt, type, callback, context) + } else { + // now this is the tricky bit + // there is a potential bug here that cause by the developer + // if they call $trigger first, the lazy won't know it's a once call + // so if in the middle they register any call with the same evt name + // then this $once call will be fucked - add this to the documentation + this.logger('($once)', lazyStoreContent); + var list = Array.from(lazyStoreContent); + // should never have more than 1 + var ref = list[0]; + var payload = ref[0]; + var ctx = ref[1]; + var t = ref[2]; + if (t && t !== type) { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this.logger('($once)', ("call run for " + evt)); + this.run(callback, payload, context || ctx); + // remove this evt from store + this.$off(evt); + } + }; + + /** + * This one event can only bind one callbackback + * @param {string} evt event name + * @param {function} callback event handler + * @param {object} [context=null] the context the event handler execute in + * @return {boolean} true bind for first time, false already existed + */ + EventService.prototype.$only = function $only (evt, callback, context) { + var this$1 = this; + if ( context === void 0 ) context = null; + + this.validate(evt, callback); + var type = 'only'; + var added = false; + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register before call $trigger + var nStore = this.normalStore; + if (!nStore.has(evt)) { + this.logger("($only)", (evt + " add to store")); + added = this.addToNormalStore(evt, type, callback, context); + } + if (lazyStoreContent !== false) { + // there are data store in lazy store + this.logger('($only)', (evt + " found data in lazy store to execute")); + var list = Array.from(lazyStoreContent); + // $only allow to trigger this multiple time on the single handler + list.forEach( function (l) { + var payload = l[0]; + var ctx = l[1]; + var t = l[2]; + if (t && t !== type) { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this$1.logger("($only)", ("call run for " + evt)); + this$1.run(callback, payload, context || ctx); + }); + } + return added; + }; + + /** + * $only + $once this is because I found a very subtile bug when we pass a + * resolver, rejecter - and it never fire because that's OLD 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; + + this.validate(evt, callback); + var type = 'onlyOnce'; + var added = false; + var lazyStoreContent = this.takeFromStore(evt); + // this is normal register before call $trigger + var nStore = this.normalStore; + if (!nStore.has(evt)) { + this.logger("($onlyOnce)", (evt + " add to store")); + added = this.addToNormalStore(evt, type, callback, context); + } + if (lazyStoreContent !== false) { + // there are data store in lazy store + this.logger('($onlyOnce)', lazyStoreContent); + var list = Array.from(lazyStoreContent); + // should never have more than 1 + var ref = list[0]; + var payload = ref[0]; + var ctx = ref[1]; + var t = ref[2]; + if (t && t !== 'onlyOnce') { + throw new Error(("You are trying to register an event already been taken by other type: " + t)) + } + this.logger("($onlyOnce)", ("call run for " + evt)); + this.run(callback, payload, context || ctx); + // remove this evt from store + this.$off(evt); + } + return added; + }; + + /** + * This is a shorthand of $off + $on added in V1.5.0 + * @param {string} evt event name + * @param {function} callback to exeucte + * @param {object} [context = null] or pass a string as type + * @param {string} [type=on] what type of method to replace + * @return {} + */ + EventService.prototype.$replace = function $replace (evt, callback, context, type) { + if ( context === void 0 ) context = null; + if ( type === void 0 ) type = 'on'; + + if (this.validateType(type)) { + this.$off(evt); + var method = this['$' + type]; + this.logger("($replace)", evt, callback); + return Reflect.apply(method, this, [evt, callback, context]) + } + throw new Error((type + " is not supported!")) + }; + + /** + * trigger the event + * @param {string} evt name NOT allow array anymore! + * @param {mixed} [payload = []] pass to fn + * @param {object|string} [context = null] overwrite what stored + * @param {string} [type=false] if pass this then we need to add type to store too + * @return {number} if it has been execute how many times + */ + EventService.prototype.$trigger = function $trigger (evt , payload , context, type) { + if ( payload === void 0 ) payload = []; + if ( context === void 0 ) context = null; + if ( type === void 0 ) type = false; + + this.validateEvt(evt); + var found = 0; + // first check the normal store + var nStore = this.normalStore; + this.logger('($trigger)', 'normalStore', nStore); + if (nStore.has(evt)) { + // @1.8.0 to add the suspend queue + var added = this.$queue(evt, payload, context, type); + this.logger('($trigger)', evt, 'found; add to queue: ', added); + if (added === true) { + this.logger('($trigger)', evt, 'not 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; + }; + + /** + * 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 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) + } + }; + + /** + * 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; + + this.validateEvt(evt); + var stores = [ this.lazyStore, this.normalStore ]; + var found = false; + stores.forEach(function (store) { + if (store.has(evt)) { + found = true; + this$1.logger('($off)', evt); + store.delete(evt); + } + }); + return found; + }; + + /** + * return all the listener from the event + * @param {string} evtName event name + * @param {boolean} [full=false] if true then return the entire content + * @return {array|boolean} listerner(s) or false when not found + */ + EventService.prototype.$get = function $get (evt, full) { + if ( full === void 0 ) full = false; + + this.validateEvt(evt); + var store = this.normalStore; + if (store.has(evt)) { + return Array + .from(store.get(evt)) + .map( function (l) { + if (full) { + return l; + } + var key = l[0]; + var callback = l[1]; + return callback; + }) + } + return false; + }; + + /** + * store the return result from the run + * @param {*} value whatever return from callback + */ + prototypeAccessors.$done.set = function (value) { + this.logger('($done)', 'value: ', value); + if (this.keep) { + this.result.push(value); + } else { + this.result = value; + } + }; + + /** + * @TODO is there any real use with the keep prop? + * getter for $done + * @return {*} whatever last store result + */ + prototypeAccessors.$done.get = function () { + if (this.keep) { + this.logger('(get $done)', this.result); + return this.result[this.result.length - 1] + } + return this.result; + }; + + Object.defineProperties( EventService.prototype, prototypeAccessors ); + + return EventService; +}(NbEventServiceBase)); + +// 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 (NBEventService) { + function JsonqlWsEvt(logger) { + if (typeof logger !== 'function') { + throw new Error("Just die here the logger is not a function!") + } + // this ee will always come with the logger + // because we should take the ee from the configuration + NBEventService.call(this, { logger: logger }); + } + + if ( NBEventService ) JsonqlWsEvt.__proto__ = NBEventService; + JsonqlWsEvt.prototype = Object.create( NBEventService && NBEventService.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)); + +/** + * 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 + } + log("Create a new Event Emitter"); + return new JsonqlWsEvt( opts.log ) +}; + +// bunch of generic helpers + +/** + * 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; }; + +// quick and dirty to turn non array to array +var toArray$1 = function (arg) { return isArray(arg) ? arg : [arg]; }; + +/** + * @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; + /* + console.info('obj', obj) + console.error(e) + throw new Error(e) + */ + } +}; + +/** + * 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('_'); +}; + +/** + * Simple check if the prop is function + * @param {*} prop input + * @return {boolean} true on success + */ +var isFunc$1 = function (prop) { + if (typeof prop === 'function') { + return true; + } + console.error(("Expect to be Function type! Got " + (typeof prop))); +}; + +/** + * 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$1(value)) + ); }, Reflect.apply(mainFn, null, args)) + ); + } +); +}; + +/** + * 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$1(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 +} + +/** + * 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; +} + +/** + * 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; + + var check = objHasProp(resolver, name); + if (overwrite === false && check !== undefined) { + // console.info(`NOT INJECTED`) + return resolver; + } + /* this will throw error! + 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 + }); + + return resolver; +} + +// 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) + ) +} + +/** + * 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; +} + +/** + * 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')) { + return contract.socket; + } + return false; +} + +/** + * @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 + * @param {boolean} [fallback=false] this is a fall back option for old code + * @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, fallback) { + if ( fallback === void 0 ) fallback = false; + + var socket = extractSocketPart(contract); + if (socket === false) { + if (fallback) { + return contract; // just return the whole contract + } + throw new JsonqlError("socket not found in contract!") + } + var nspSet = {}; + var size = 0; + var publicNamespace; + for (var resolverName in socket) { + var params = socket[resolverName]; + var namespace = params.namespace; + if (namespace) { + if (!nspSet[namespace]) { + ++size; + nspSet[namespace] = {}; + } + nspSet[namespace][resolverName] = params; + if (!publicNamespace) { + if (params.public) { + publicNamespace = namespace; + } + } + } + } + return { size: size, nspSet: nspSet, publicNamespace: publicNamespace } +} + +// constants + +var MISSING_PROP_ERR = 'Missing property in contract!'; + +var UNKNOWN_RESULT = 'UKNNOWN RESULT!'; + +var MY_NAMESPACE = 'myNamespace'; + +// mapping the resolver to their respective nsp + +/** + * Just make sure the object contain what we are looking for + * @param {object} opts configuration from checkOptions + * @return {object} the target content + */ +var getResolverList = function (contract) { + var result = extractSocketPart(contract); + if (result !== false) { + return result + } + throw new JsonqlResolverNotFoundError(MISSING_PROP_ERR) +}; + +/** + * process the contract first + * @param {object} opts configuration + * @return {object} sorted list + */ +function processContract(opts) { + var obj, obj$1; + + var contract = opts.contract; + var enableAuth = opts.enableAuth; + if (enableAuth) { + return groupByNamespace(contract) + } + return ( obj$1 = {}, obj$1[NSP_SET] = ( obj = {}, obj[JSONQL_PATH] = getResolverList(contract), obj ), obj$1[PUBLIC_NAMESPACE] = JSONQL_PATH, obj$1 ) +} + +// group all the small functions here +// we shouldn't do this anymore +var fixWss = function (url, serverType) { + // ws only allow ws:// path + if (serverType === JS_WS_NAME) { + return url.replace('http://', 'ws://') + } + return url +}; + +/** + * get a stock host name from browser + */ +var getHostName = function () { + try { + return [window.location.protocol, window.location.host].join('//') + } catch(e) { + throw new JsonqlValidationError(e) + } +}; + +// take out from the resolver-methods + + +/** + * @TODO this is now become unnecessary because the login is a slave to the + * http-client - but keep this for now and see what we want to do with it later + * break out from createAuthMethods to allow chaining call + * @param {object} obj the main client object + * @param {object} opts configuration + * @param {object} ee event emitter + * @return {array} [ obj, opts, ee ] + */ +var setupLoginHandler = function (obj, opts, ee) { return [ + injectToFn(obj, opts.loginHandlerName, function loginHandler(token) { + if (token && isString$1(token)) { + return ee.$trigger(LOGIN_EVENT_NAME, [token]) + } + // should trigger a global error instead @TODO + throw new JsonqlValidationError(opts.loginHandlerName, ("Unexpected token " + token)) + }), + ee, + opts +]; }; + +/** + * break out from createAuthMethods to allow chaining call - final in chain + * @param {object} obj the main client object + * @param {object} opts configuration + * @param {object} ee event emitter + * @return {array} [ obj, ee ] + */ +var setupLogoutHandler = function (obj, opts, ee) { return [ + injectToFn(obj, opts.logoutHandlerName, function logoutHandler() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + ee.$trigger(LOGOUT_EVENT_NAME, args); + }), + ee +]; }; + + +/** + * This event will fire when the socket.io.on('connection') and ws.onopen + * Plus this will check if it's the private namespace that fired the event + * @param {object} obj the client itself + * @param {object} ee Event Emitter + * @return {object} obj with onLogin prop + */ +function createOnLoginhandler(obj, ee) { + return objDefineProps(obj, ON_LOGIN_PROP_NAME, function onLoginCallbackHandler(onLoginCallback) { + if (isFunc(onLoginCallback)) { + // only one callback can registered with it, TBC + ee.$only(ON_LOGIN_PROP_NAME, onLoginCallback); + } + }) +} + +/** + * Create auth related methods + * @param {object} obj the client itself + * @param {object} opts configuration + * @param {object} ee Event Emitter + * @return {object} obj with auth methods if any + */ +function createAuthMethods(obj, opts, ee) { + return chainFns( + setupLoginHandler, + setupLogoutHandler, + createOnLoginhandler + )(obj, opts, ee) +} + +// breaking it up further to share between methods + +/** + * break out to use in different places to handle the return from server + * @param {object} data from server + * @param {function} resolver NOT from promise + * @param {function} rejecter NOT from promise + * @return {void} nothing + */ +function respondHandler(data, resolver, rejecter) { + if (isObjectHasKey$1(data, ERROR_KEY)) { + // debugFn('-- rejecter called --', data[ERROR_KEY]) + rejecter(data[ERROR_KEY]); + } else if (isObjectHasKey$1(data, DATA_KEY)) { + // debugFn('-- resolver called --', data[DATA_KEY]) + resolver(data[DATA_KEY]); + } else { + // debugFn('-- UNKNOWN_RESULT --', data) + rejecter({message: UNKNOWN_RESULT, error: data}); + } +} + +// the actual trigger call method + +/** + * just wrapper + * @param {object} ee EventEmitter + * @param {string} namespace where this belongs + * @param {string} resolverName resolver + * @param {array} args arguments + * @return {void} nothing + */ +function actionCall(ee, namespace, resolverName, args) { + if ( args === void 0 ) args = []; + + var eventName = createEvt(namespace, EMIT_REPLY_TYPE); + // const RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME + + debugFn(("actionCall: " + eventName + " --> " + resolverName), args); + // this could be a problem + ee.$trigger(eventName, [resolverName, toArray$1(args)]); + + // then we need to listen to the event callback here as well + return new Promise(function (resolver, rejecter) { + ee.$on( + createEvt(namespace, resolverName, ON_RESULT_PROP_NAME), + function actionCallResultHandler(result) { + + debugFn("got the first result", result); + + respondHandler(result, resolver, rejecter); + } + ); + }) +} + +// pairing with the server vesrion SEND_MSG_PROP_NAME +// last of the chain so only return the resolver (fn) +var setupSend = function (fn, ee, namespace, resolverName, params) { return ( + objDefineProps$1(fn, SEND_MSG_PROP_NAME, function sendSetter(messagePayload) { + // debugFn('got payload for', messagePayload) + // @NOTE change from sync interface to async @ 1.0.0 + // this way we will able to catch all the error(s) + validateAsync$1(toArray$1(messagePayload), params.params, true) + .then(function (result) { + // here is the different we don't throw error instead we trigger onError + if (result[ERROR_KEY] && result[ERROR_KEY].length) { + // debugFn(`got ERROR_KEY`, result[ERROR_KEY]) + ee.$call( + createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), + [new JsonqlValidationError(resolverName, result[ERROR_KEY])] + ); + } else { + // return it just for the catch to work - if any + return actionCall(ee, namespace, resolverName, messagePayload) + } + }) + .catch(function (err) { + // debugFn(`error after validateAsync`, err) + ee.$call( + createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), + [new JsonqlValidationError(resolverName, err)] + ); + }); + }, function sendGetter() { // add in 1.1.4 + return function sendGetterAction() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return validateAsync$1(args, params.params, true) + .then(function (_args) { return actionCall(ee, namespace, resolverName, _args); }) + .catch(finalCatch) + } + }) +); }; + +// break up the original setup resolver method here + +/** + * The first one in the chain + * @return {array} + */ +var setupNamespace = function (fn, ee, namespace, resolverName, params) { return [ + injectToFn(fn, MY_NAMESPACE, namespace), + ee, + namespace, + resolverName, + params +]; }; + +// onResult handler +var setupOnResult = function (fn, ee, namespace, resolverName, params) { return [ + objDefineProps$1(fn, ON_RESULT_PROP_NAME, function(resultCallback) { + if (isFunc$1(resultCallback)) { + ee.$on( + createEvt(namespace, resolverName, ON_RESULT_PROP_NAME), + function resultHandler(result) { + respondHandler(result, resultCallback, function (error) { + ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error); + }); + } + ); + } + }), + ee, + namespace, + resolverName, + params +]; }; + +// we do need to add the send prop back because it's the only way to deal with +// bi-directional data stream +var setupOnMessage = function (fn, ee, namespace, resolverName, params) { return [ + objDefineProps$1(fn, ON_MESSAGE_PROP_NAME, function(messageCallback) { + // we expect this to be a function + if (isFunc$1(messageCallback)) { + // did that add to the callback + var onMessageCallback = function (args) { + respondHandler(args, messageCallback, function (error) { + ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error); + }); + }; + // register the handler for this message event + ee.$only(createEvt(namespace, resolverName, ON_MESSAGE_PROP_NAME), onMessageCallback); + } + }), + ee, + namespace, + resolverName, + params +]; }; + +// add an ON_ERROR_PROP_NAME handler +var setupOnError = function (fn, ee, namespace, resolverName, params) { return [ + objDefineProps$1(fn, ON_ERROR_PROP_NAME, function(resolverErrorHandler) { + if (isFunc$1(resolverErrorHandler)) { + // please note ON_ERROR_PROP_NAME can add multiple listners + ee.$only(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), resolverErrorHandler); + } + }), + ee, + namespace, + resolverName, + params +]; }; + +/** + * Add extra property to the resolver + * @param {string} namespace where this belongs + * @param {string} resolverName name as event name + * @param {object} params from contract + * @param {function} fn resolver function + * @param {object} ee EventEmitter + * @return {function} resolver + */ +function setupResolver(namespace, resolverName, params, fn, ee) { + // also need to setup a getter to get back the namespace of this resolver + var args = [setupNamespace]; + args.push(setupOnResult, setupOnMessage, setupOnError); + args.push(setupSend); + // get the executor + var executor = Reflect.apply(chainFns, null, args); + + return Reflect.apply(executor, null, [fn, ee, namespace, resolverName, params]) +} + +// put all the resolver related methods here to make it more clear +// import { CB_FN_NAME } from '../options/constants' + +/** + * create the actual function to send message to server + * @param {object} ee EventEmitter instance + * @param {string} namespace this resolver end point + * @param {string} resolverName name of resolver as event name + * @param {object} params from contract + * @return {function} resolver + */ +function createResolver(ee, namespace, resolverName, params) { + // note we pass the new withResult=true option + return function() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return validateAsync$1(args, params.params, true) + .then(function (_args) { return actionCall(ee, namespace, resolverName, _args); }) + .catch(finalCatch) + } +} + +/** + * step one get the obj map with the namespace + * @param {object} opts configuration + * @param {object} ee EventEmitter + * @param {object} nspSet resolvers index by their namespace + * @return {promise} resolve the obj mapped, and start the chain + */ +function generateResolvers(opts, ee, nspSet) { + var obj = {}; + // const { useCallbackStyle } = opts; // @1.2.1 + for (var namespace in nspSet) { + var list = nspSet[namespace]; + for (var resolverName in list) { + // resolverNames.push(resolverName) + var params = list[resolverName]; + var fn = createResolver(ee, namespace, resolverName, params); + // this should set as a getter therefore can not be overwrite by accident + // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee) + obj = injectToFn(obj, resolverName, setupResolver(namespace, resolverName, params, fn, ee)); + } + } + // resolve the obj to start the chain + // chain the result to allow the chain processing + return [ obj, opts, ee, nspSet ] +} + +/** + * The problem is the namespace can have more than one + * and we only have on onError message + * @param {object} obj the client itself + * @param {object} opts configuration + * @param {object} ee Event Emitter + * @param {object} nspSet namespace keys + * @return {array} [obj, opts, ee] + */ +function createNamespaceErrorHandler(obj, opts, ee, nspSet) { + return [ + // using the onError as name + // @TODO we should follow the convention earlier + // make this a setter for the obj itself + objDefineProps$1(obj, ON_ERROR_PROP_NAME, function namespaceErrorCallbackHandler(namespaceErrorHandler) { + if (isFunc$1(namespaceErrorHandler)) { + // please note ON_ERROR_PROP_NAME can add multiple listners + for (var namespace in nspSet) { + // 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_PROP_NAME), namespaceErrorHandler); + } + } + }), + opts, + ee + ] +} + +/** + * This event will fire when the socket.io.on('connection') and ws.onopen + * @param {object} obj the client itself + * @param {object} opts configuration + * @param {object} ee Event Emitter + * @return {array} [ obj, opts, ee ] + */ +function createOnReadyhandler(obj, opts, ee) { + return [ + objDefineProps$1(obj, ON_READY_PROP_NAME, function onReadyCallbackHandler(onReadyCallback) { + if (isFunc$1(onReadyCallback)) { + // reduce it down to just one flat level + ee.$on(ON_READY_PROP_NAME, onReadyCallback); + } + }), + opts, + ee + ] +} + +// resolvers generator + +/** + * prepare the methods + * @param {object} opts configuration + * @param {object} nspMap resolvers index by their namespace + * @param {object} ee EventEmitter + * @return {object} of resolvers + * @public + */ +function generator(opts, nspMap, ee) { + var nspSet = nspMap.nspSet; + var enableAuth = opts.enableAuth; + var args = [ + generateResolvers, + createNamespaceErrorHandler, + createOnReadyhandler ]; + if (enableAuth) { + args.push( + createAuthMethods + ); + } else { + // we just return the obj itself + args.push( + function (obj) { return obj; } + ); + } + + // run it + var fn = Reflect.apply(chainFns, null, args); + return fn(opts, ee, nspSet) +} + +var obj, obj$1; +// import { AVAILABLE_SERVERS } from './constants' +var AVAILABLE_METHODS = [IO_ROUNDTRIP_LOGIN, IO_HANDSHAKE_LOGIN]; + +var wsCoreDefaultOptions = { + // useCallbackStyle: createConfig(false, [BOOLEAN_TYPE]), abandoned in 0.6.0 + loginHandlerName: createConfig$1(ISSUER_NAME, [STRING_TYPE]), + logoutHandlerName: createConfig$1(LOGOUT_NAME, [STRING_TYPE]), + // this is for socket.io + loginMethod: createConfig$1(IO_HANDSHAKE_LOGIN, [STRING_TYPE], ( obj = {}, obj[ENUM_KEY] = AVAILABLE_METHODS, obj )), + // we will use this for determine the socket.io client type as well - @TODO remove or rename + useJwt: createConfig$1(true, [BOOLEAN_TYPE, STRING_TYPE]), + // this is going to replace the use of useJwt === string next + authStrKey: createConfig$1(null, [STRING_TYPE]), + hostname: createConfig$1(false, [STRING_TYPE]), + namespace: createConfig$1(JSONQL_PATH, [STRING_TYPE]), + wsOptions: createConfig$1({}, [OBJECT_TYPE]), + // make this null as default don't set this here, only set in the down stream + // serverType: createConfig(null, [STRING_TYPE], {[ENUM_KEY]: AVAILABLE_SERVERS}), + // we require the contract already generated and pass here + contract: createConfig$1({}, [OBJECT_TYPE], ( obj$1 = {}, obj$1[CHECKER_KEY] = isContract, obj$1 )), + enableAuth: createConfig$1(false, [BOOLEAN_TYPE]), + token: createConfig$1(false, [STRING_TYPE]) +}; + +// constant props +var wsCoreConstProps = { + // contract: null, + eventEmitter: null, + // we unify the two different client into one now + // only expect different parameter + nspClient: null, + nspAuthClient: null, + // contructed path + wssPath: '' +}; + +// create options + +/** + * wrapper method to check this already did the pre check + * @param {object} config user supply config + * @param {object} defaultOptions for checking + * @param {object} constProps user supply const props + * @return {promise} resolve to the checked opitons + */ +function checkOptionsWrapper(config, defaultOptions, constProps) { + var wsConstProps = Object.assign(wsCoreConstProps, constProps); + var defaultCheckOptions = Object.assign(wsCoreDefaultOptions, defaultOptions); + /* + const fn = postConfigCheck(checkMap, constProps, checkConfig) + return fn(config) + */ + return checkConfigAsync(config, defaultCheckOptions, wsConstProps) +} + +/** + * Taking the then part from the method below + * @param {object} opts + * @return {promise} opts all done + */ +function postWsOptions(opts) { + return Promise.resolve(opts) + .then(function (opts) { + if (!opts.hostname) { + opts.hostname = getHostName(); + } + // @TODO the contract now will supply the namespace information + // and we need to use that to group the namespace call + opts.wssPath = fixWss([opts.hostname, opts.namespace].join('/'), opts.serverType); + // debug('CONFIGURATION OPTIONS', opts) + return opts + }) +} + +/** + * check the configuration + * @param {object} config user supplied configuration + * @param {object} defaultOptions the check map + * @param {object} constProps developer supplied configuration + * @return {object} after checked + */ +function checkWsCoreOptions(config, defaultOptions, constProps) { + return checkOptionsWrapper(config, defaultOptions, constProps) + .then(postWsOptions) +} + +// the top level API + +/** + * 0.5.0 we break up the wsClientCore in two parts one without the config check + * @param {function} socketClientResolver + * @param {object} config the already checked config + */ +function wsClientCoreAction(socketClientResolver, config) { + return Promise + .resolve(config) + .then(getLogFn) + .then(function (opts) { return ({ + opts: opts, + nspMap: processContract(opts), + ee: getEventEmitter(opts) + }); }) + .then( + function (ref) { + var opts = ref.opts; + var nspMap = ref.nspMap; + var ee = ref.ee; + + return socketClientResolver(opts, nspMap, ee); + } + ) + .then( + function (ref) { + var opts = ref.opts; + var nspMap = ref.nspMap; + var ee = ref.ee; + + return generator(opts, nspMap, ee); + } + ) + .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} socketClientResolver this is the one method export by various clients + * @param {object} [defaultOptions={}] 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(socketClientResolver, defaultOptions, constProps) { + if ( defaultOptions === void 0 ) defaultOptions = {}; + if ( constProps === void 0 ) constProps = {}; + + // we need to inject property to this client later + // therefore we need to do it this way + return function (config) { + if ( config === void 0 ) config = {}; + + return ( + checkWsCoreOptions(config, defaultOptions, constProps) + .then(function (opts) { return wsClientCoreAction(socketClientResolver, opts); }) + ); + } + +} + +var QUERY_ARG_NAME = 'args'; +var TIMESTAMP_PARAM_NAME = 'TS'; +var NO_STATUS_CODE$1 = -1; +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 EMIT_REPLY_TYPE$1 = 'emit'; +var ACKNOWLEDGE_REPLY_TYPE = 'acknowledge'; +var ERROR_TYPE = 'error'; + +var JS_WS_SOCKET_IO_NAME = 'socket.io'; +var JS_WS_NAME$1 = 'ws'; + +// for ws client +var ON_MESSAGE_PROP_NAME$1 = 'onMessage'; +var ON_RESULT_PROP_NAME$1 = 'onResult'; +var ON_ERROR_PROP_NAME$1 = 'onError'; +var ON_READY_PROP_NAME$1 = 'onReady'; +var ON_LOGIN_PROP_NAME$1 = 'onLogin'; // new @1.8.6 +// breaking change from 1.8.8 the above name was the name below +// the names are using in the new resolver.on getter interface +var MESSAGE_PROP_NAME = 'message'; +var RESULT_PROP_NAME = 'result'; +var ERROR_PROP_NAME = 'error'; +var READY_PROP_NAME = 'ready'; +var LOGIN_PROP_NAME = 'login'; // new @1.8.6 +var NOT_LOGIN_ERR_MSG = 'NOT LOGIN'; +var TOKEN_PARAM_NAME = 'token'; + +// jsonql-ws-core takes over the check configuration +// constant props +var wsClientConstProps = { + version: 'version: 1.1.0 module: cjs', // will get replace + serverType: JS_WS_NAME$1 +}; + +var wsClientAppProps = {}; + +// pass the different type of ws to generate the client +/** + * WebSocket is strict about the path, therefore we need to make sure before it goes in + * @param {string} url input url + * @return {string} url with correct path name + */ +var fixWss$1 = function (url) { + var uri = url.toLowerCase(); + if (uri.indexOf('http') > -1) { + if (uri.indexOf('https') > -1) { + return uri.replace('https', 'wss') + } + return uri.replace('http', 'ws') + } + return uri +}; + +/** + * The bug was in the wsOptions where ws doesn't need it but socket.io do + * therefore the object was pass as second parameter! + * @param {object} WebSocket the client or node version of ws + * @param {boolean} auth if it's auth then 3 param or just one + */ +function createWsClient(WebSocket, auth) { + if ( auth === void 0 ) auth = false; + + if (auth === false) { + return function createWsClientHandler(url) { + return new WebSocket(fixWss$1(url)) + } + } + + /** + * Create a client with auth token + * @param {string} url start with ws:// @TODO check this? + * @param {string} token the jwt token + * @return {object} ws instance + */ + return function createWsAuthClientHandler(url, token) { + var ws_url = fixWss$1(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 + } + } +} + +/** + * 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; + +/** Detect free variable `global` from Node.js. */ +var freeGlobal$1 = typeof global$1 == 'object' && global$1 && global$1.Object === Object && global$1; + +/** Detect free variable `self`. */ +var freeSelf$1 = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root$1 = freeGlobal$1 || freeSelf$1 || Function('return this')(); + +/** 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; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString$2 = objectProto$f.toString; + +/** Built-in value references. */ +var symToStringTag$2 = Symbol$1 ? Symbol$1.toStringTag : undefined; + +/** + * 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; + +/** + * 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); +} + +/** + * 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 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike$1(value) { + return value != null && typeof value == 'object'; +} + +/** + * 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$1(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$2 = '[object Symbol]'; + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol$1(value) { + return typeof value == 'symbol' || + (isObjectLike$1(value) && baseGetTag$1(value) == symbolTag$2); +} + +/** Used as references for various `Number` constants. */ +var INFINITY$2 = 1 / 0; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto$2 = Symbol$1 ? Symbol$1.prototype : undefined, + symbolToString$1 = symbolProto$2 ? symbolProto$2.toString : undefined; + +/** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString$1(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray$1(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap$1(value, baseToString$1) + ''; + } + if (isSymbol$1(value)) { + return symbolToString$1 ? symbolToString$1.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY$2) ? '-0' : result; +} + +/** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ +function baseSlice$1(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; +} + +/** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ +function castSlice$1(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice$1(array, start, end); +} + +/** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseFindIndex$1(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; +} + +/** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ +function baseIsNaN$1(value) { + return value !== value; +} + +/** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function strictIndexOf$1(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; +} + +/** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseIndexOf$1(array, value, fromIndex) { + return value === value + ? strictIndexOf$1(array, value, fromIndex) + : baseFindIndex$1(array, baseIsNaN$1, fromIndex); +} + +/** + * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the last unmatched string symbol. + */ +function charsEndIndex$1(strSymbols, chrSymbols) { + var index = strSymbols.length; + + while (index-- && baseIndexOf$1(chrSymbols, strSymbols[index], 0) > -1) {} + return index; +} + +/** + * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the first unmatched string symbol. + */ +function charsStartIndex$1(strSymbols, chrSymbols) { + var index = -1, + length = strSymbols.length; + + while (++index < length && baseIndexOf$1(chrSymbols, strSymbols[index], 0) > -1) {} + return index; +} + +/** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function asciiToArray$1(string) { + return string.split(''); +} + +/** Used to compose unicode character classes. */ +var rsAstralRange$2 = '\\ud800-\\udfff', + rsComboMarksRange$2 = '\\u0300-\\u036f', + reComboHalfMarksRange$2 = '\\ufe20-\\ufe2f', + rsComboSymbolsRange$2 = '\\u20d0-\\u20ff', + rsComboRange$2 = rsComboMarksRange$2 + reComboHalfMarksRange$2 + rsComboSymbolsRange$2, + rsVarRange$2 = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsZWJ$2 = '\\u200d'; + +/** 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/). */ +var reHasUnicode$1 = RegExp('[' + rsZWJ$2 + rsAstralRange$2 + rsComboRange$2 + rsVarRange$2 + ']'); + +/** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ +function hasUnicode$1(string) { + return reHasUnicode$1.test(string); +} + +/** Used to compose unicode character classes. */ +var rsAstralRange$3 = '\\ud800-\\udfff', + rsComboMarksRange$3 = '\\u0300-\\u036f', + reComboHalfMarksRange$3 = '\\ufe20-\\ufe2f', + rsComboSymbolsRange$3 = '\\u20d0-\\u20ff', + rsComboRange$3 = rsComboMarksRange$3 + reComboHalfMarksRange$3 + rsComboSymbolsRange$3, + rsVarRange$3 = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsAstral$1 = '[' + rsAstralRange$3 + ']', + rsCombo$1 = '[' + rsComboRange$3 + ']', + rsFitz$1 = '\\ud83c[\\udffb-\\udfff]', + rsModifier$1 = '(?:' + rsCombo$1 + '|' + rsFitz$1 + ')', + rsNonAstral$1 = '[^' + rsAstralRange$3 + ']', + rsRegional$1 = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair$1 = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsZWJ$3 = '\\u200d'; + +/** Used to compose unicode regexes. */ +var reOptMod$1 = rsModifier$1 + '?', + rsOptVar$1 = '[' + rsVarRange$3 + ']?', + rsOptJoin$1 = '(?:' + rsZWJ$3 + '(?:' + [rsNonAstral$1, rsRegional$1, rsSurrPair$1].join('|') + ')' + rsOptVar$1 + reOptMod$1 + ')*', + rsSeq$1 = rsOptVar$1 + reOptMod$1 + rsOptJoin$1, + rsSymbol$1 = '(?:' + [rsNonAstral$1 + rsCombo$1 + '?', rsCombo$1, rsRegional$1, rsSurrPair$1, rsAstral$1].join('|') + ')'; + +/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ +var reUnicode$1 = RegExp(rsFitz$1 + '(?=' + rsFitz$1 + ')|' + rsSymbol$1 + rsSeq$1, 'g'); + +/** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function unicodeToArray$1(string) { + return string.match(reUnicode$1) || []; +} + +/** + * Converts `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function stringToArray$1(string) { + return hasUnicode$1(string) + ? unicodeToArray$1(string) + : asciiToArray$1(string); +} + +/** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ +function toString$1(value) { + return value == null ? '' : baseToString$1(value); +} + +/** Used to match leading and trailing whitespace. */ +var reTrim$1 = /^\s+|\s+$/g; + +/** + * Removes leading and trailing whitespace or specified characters from `string`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {string} Returns the trimmed string. + * @example + * + * _.trim(' abc '); + * // => 'abc' + * + * _.trim('-_-abc-_-', '_-'); + * // => 'abc' + * + * _.map([' foo ', ' bar '], _.trim); + * // => ['foo', 'bar'] + */ +function trim$1(string, chars, guard) { + string = toString$1(string); + if (string && (guard || chars === undefined)) { + return string.replace(reTrim$1, ''); + } + if (!string || !(chars = baseToString$1(chars))) { + return string; + } + var strSymbols = stringToArray$1(string), + chrSymbols = stringToArray$1(chars), + start = charsStartIndex$1(strSymbols, chrSymbols), + end = charsEndIndex$1(strSymbols, chrSymbols) + 1; + + return castSlice$1(strSymbols, start, end).join(''); +} + +// bunch of generic helpers + +/** + * DIY in Array + * @param {array} arr to check from + * @param {*} value to check against + * @return {boolean} true on found + */ +var inArray$2 = function (arr, value) { return !!arr.filter(function (a) { return a === value; }).length; }; + +// quick and dirty to turn non array to array +var toArray$2 = function (arg) { return isArray$1(arg) ? arg : [arg]; }; + +/** + * @param {object} obj for search + * @param {string} key target + * @return {boolean} true on success + */ +var isObjectHasKey$2 = function(obj, key) { + try { + var keys = Object.keys(obj); + return inArray$2(keys, key) + } catch(e) { + // @BUG when the obj is not an OBJECT we got some weird output + return false; + /* + console.info('obj', obj) + console.error(e) + throw new Error(e) + */ + } +}; + +/** + * create a event name + * @param {string[]} args + * @return {string} event name for use + */ +var createEvt$1 = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return args.join('_'); +}; + +// custom validation error class +// when validaton failed +var JsonqlValidationError$1 = /*@__PURE__*/(function (Error) { + function JsonqlValidationError() { + 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 = JsonqlValidationError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlValidationError); + } + } + + if ( Error ) JsonqlValidationError.__proto__ = Error; + JsonqlValidationError.prototype = Object.create( Error && Error.prototype ); + JsonqlValidationError.prototype.constructor = JsonqlValidationError; + + var staticAccessors = { name: { configurable: true } }; + + staticAccessors.name.get = function () { + return 'JsonqlValidationError'; + }; + + Object.defineProperties( JsonqlValidationError, staticAccessors ); + + return JsonqlValidationError; +}(Error)); + +/** + * 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 ]; + + Error.apply(this, args); + + this.message = args[0]; + this.detail = args[1]; + + this.className = JsonqlError.name; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, JsonqlError); + // this.detail = this.stack; + } + } + + if ( Error ) JsonqlError.__proto__ = Error; + JsonqlError.prototype = Object.create( Error && Error.prototype ); + JsonqlError.prototype.constructor = JsonqlError; + + var staticAccessors = { name: { configurable: true },statusCode: { configurable: true } }; + + staticAccessors.name.get = function () { + return 'JsonqlError'; + }; + + staticAccessors.statusCode.get = function () { + return NO_STATUS_CODE$1; + }; + + Object.defineProperties( JsonqlError, staticAccessors ); + + return JsonqlError; +}(Error)); + +// split the contract into the node side and the generic side + +/** + * @NOTE ported from jsonql-ws-client + * Got to make sure the connection order otherwise + * it will hang + * @param {object} nspSet contract + * @param {string} publicNamespace like the name said + * @return {array} namespaces in order + */ +function getNamespaceInOrder(nspSet, publicNamespace) { + var names = []; // need to make sure the order! + for (var namespace in nspSet) { + if (namespace === publicNamespace) { + names[1] = namespace; + } else { + names[0] = namespace; + } + } + return names; +} + +/** + * @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$3 = '[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 + * + * _.isString(1); + * // => false + */ +function isString$2(value) { + return typeof value == 'string' || + (!isArray$1(value) && isObjectLike$1(value) && baseGetTag$1(value) == stringTag$3); +} + +// 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 ) +); +}; + +/** + * Get name from the payload (ported back from jsonql-koa) + * @param {*} payload to extract from + * @return {string} name + */ +function getNameFromPayload(payload) { + return Object.keys(payload)[0] +} + +/** + * 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$2(resolverName) && isArray$1(args)) { + var payload = formatPayload(args); + if (jsonp === true) { + return payload; + } + return createDeliverable(resolverName, payload) + } + throw new JsonqlValidationError$1("[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)) +} + +// constants + +var SOCKET_IO = JS_WS_SOCKET_IO_NAME; + +var EMIT_EVT = EMIT_REPLY_TYPE$1; + +// since both the ws and io version are +// pre-defined in the client-generator +// and this one will have the same parameters +// and the callback is identical + +/** + * wrapper method to create a nsp without login + * @param {string|boolean} namespace namespace url could be false + * @param {object} opts configuration + * @return {object} ws client instance + */ +function createNspClient(namespace, opts) { + var hostname = opts.hostname; + var wssPath = opts.wssPath; + var wsOptions = opts.wsOptions; + var nspClient = opts.nspClient; + var url = namespace ? [hostname, namespace].join('/') : wssPath; + return nspClient(url, wsOptions) +} + +/** + * wrapper method to create a nsp with token auth + * @param {string} namespace namespace url + * @param {object} opts configuration + * @return {object} ws client instance + */ +function createNspAuthClient(namespace, opts) { + var hostname = opts.hostname; + var wssPath = opts.wssPath; + var token = opts.token; + var wsOptions = opts.wsOptions; + var nspAuthClient = opts.nspAuthClient; + var url = namespace ? [hostname, namespace].join('/') : wssPath; + if (token && typeof token !== 'string') { + throw new Error(("Expect token to be string, but got " + token)) + } + return nspAuthClient(url, token, wsOptions) +} + +// validate string type +/** + * @param {string} value expected value + * @return {boolean} true if OK + */ +var checkIsString$1 = function(value) { + return (trim$1(value) !== '') ? isString$2(value) : false; +}; + +// export +var isString$3 = checkIsString$1; + +// making all the functionality on it's own +// import { WatchClass } from './watch' + +var SuspendClass$1 = function SuspendClass() { + // suspend, release and queue + this.__suspend__ = null; + this.queueStore = new Set(); + /* + this.watch('suspend', function(value, prop, oldValue) { + this.logger(`${prop} set from ${oldValue} to ${value}`) + // it means it set the suspend = true then release it + if (oldValue === true && value === false) { + // we want this happen after the return happens + setTimeout(() => { + this.release() + }, 1) + } + return value; // we need to return the value to store it + }) + */ +}; + +var prototypeAccessors$1 = { $suspend: { configurable: true },$queues: { configurable: true } }; + +/** + * setter to set the suspend and check if it's boolean value + * @param {boolean} value to trigger + */ +prototypeAccessors$1.$suspend.set = function (value) { + var this$1 = this; + + if (typeof value === 'boolean') { + var lastValue = this.__suspend__; + this.__suspend__ = value; + this.logger('($suspend)', ("Change from " + lastValue + " --> " + value)); + if (lastValue === true && value === false) { + setTimeout(function () { + this$1.release(); + }, 1); + } + } else { + throw new Error("$suspend only accept Boolean value!") + } +}; + +/** + * queuing call up when it's in suspend mode + * @param {any} value + * @return {Boolean} true when added or false when it's not + */ +SuspendClass$1.prototype.$queue = function $queue () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (this.__suspend__ === true) { + this.logger('($queue)', 'added to $queue', args); + // there shouldn't be any duplicate ... + this.queueStore.add(args); + } + return this.__suspend__; +}; + +/** + * a getter to get all the store queue + * @return {array} Set turn into Array before return + */ +prototypeAccessors$1.$queues.get = function () { + var size = this.queueStore.size; + this.logger('($queues)', ("size: " + size)); + if (size > 0) { + return Array.from(this.queueStore) + } + return [] +}; + +/** + * Release the queue + * @return {int} size if any + */ +SuspendClass$1.prototype.release = function release () { + var this$1 = this; + + var size = this.queueStore.size; + this.logger('(release)', ("Release was called " + size)); + if (size > 0) { + var queue = Array.from(this.queueStore); + this.queueStore.clear(); + this.logger('queue', queue); + queue.forEach(function (args) { + this$1.logger(args); + Reflect.apply(this$1.$trigger, this$1, args); + }); + this.logger(("Release size " + (this.queueStore.size))); + } +}; + +Object.defineProperties( SuspendClass$1.prototype, prototypeAccessors$1 ); + +// group all the small functions here + +/** + * Unbind the event + * @param {object} ee EventEmitter + * @param {string} namespace + * @return {void} + */ +var clearMainEmitEvt = function (ee, namespace) { + var nsps = toArray$2(namespace); + nsps.forEach(function (n) { + ee.$off(createEvt$1(n, EMIT_REPLY_TYPE$1)); + }); +}; + +// 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 + * @param {object} opts configuration + * @return {void} + */ +function triggerNamespacesOnError(ee, namespaces, message, opts) { + if ( opts === void 0 ) opts = {}; + + var useCallbackStyle = opts.useCallbackStyle; + var ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME$1; + namespaces.forEach( function (namespace) { + ee.$call(createEvt$1(namespace, ERROR_SUBFIX), [{ message: message, namespace: namespace }]); + }); +} + +// This is share between different clients so we export it + +/** + * A fake ee handler + * @param {string} namespace nsp + * @param {object} ee EventEmitter + * @param {object} opts configuration + * @return {void} + */ +var notLoginWsHandler = function (namespace, ee, opts) { + var useCallbackStyle = opts.useCallbackStyle; + var log = opts.log; + var ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME$1; + var RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME$1; + ee.$only( + createEvt$1(namespace, EMIT_EVT), + function notLoginHandlerCallback(resolverName, args) { + + log('[notLoginHandler] 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$1(namespace, resolverName, ERROR_SUBFIX), [error]); + // also trigger the result handler, but wrap inside the error key + ee.$call(createEvt$1(namespace, resolverName, RESULT_SUBFIX), [{ 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 +); }; + +/** + * centralize all the comm in one place + * @param {object} opts configuration + * @param {array} namespaces namespace(s) + * @param {object} ee Event Emitter instance + * @param {function} bindWsHandler binding the ee to ws --> this is the core bit + * @param {array} namespaces array of namespace available + * @param {object} nsps namespaced nsp + * @return {void} nothing + */ +function clientEventHandler(opts, nspMap, ee, bindWsHandler, namespaces, nsps) { + // @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 log = opts.log; + // 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 a waterfall here to make sure + // one is execute then the other + namespaces.forEach(function (namespace) { + isPrivate = privateNamespace === namespace; + if (nsps[namespace]) { + log('[call bindWsHandler]', isPrivate, namespace); + var args = [namespace, nsps[namespace], ee, isPrivate, opts]; + if (opts.serverType === SOCKET_IO) { + var nspSet = nspMap.nspSet; + args.push(nspSet[namespace]); + } + Reflect.apply(bindWsHandler, null, args); + } else { + // a dummy placeholder + notLoginWsHandler(namespace, ee, opts); + } + }); + // this will be available regardless enableAuth + // because the server can log the client out + ee.$on(LOGOUT_EVENT_NAME$1, function logoutEvtHandler() { + log('LOGOUT_EVENT_NAME'); + // disconnect(nsps, opts.serverType) + // we need to issue error to all the namespace onError handler + triggerNamespacesOnError(ee, namespaces, LOGOUT_EVENT_NAME$1); + // rebind all of the handler to the fake one + namespaces.forEach( function (namespace) { + clearMainEmitEvt(ee, namespace); + // clear out the nsp + nsps[namespace] = false; + // add a NOT LOGIN error if call + notLoginWsHandler(namespace, ee, opts); + }); + }); +} + +// take the ws reply data for use + +var keys$1 = [ WS_REPLY_TYPE, WS_EVT_NAME, WS_DATA_NAME ]; + +/** + * @param {object} payload should be string when reply but could be transformed + * @return {boolean} true is OK + */ +var isWsReply = function (payload) { + var data = payload.data; + if (data) { + var result = keys$1.filter(function (key) { return isObjectHasKey$2(data, key); }); + return (result.length === keys$1.length) ? data : false + } + return false +}; + +/** + * @param {object} payload This is the entire ws Event Object + * @return {object} false on failed + */ +var extractWsPayload = function (payload) { + var data = payload.data; + var json = isString$3(data) ? JSON.parse(data) : data; + var fdata; + if ((fdata = isWsReply(json)) !== false) { + return { + resolverName: fdata[WS_EVT_NAME], + data: fdata[WS_DATA_NAME], + type: fdata[WS_REPLY_TYPE] + } + } + throw new JsonqlError$1('payload can not be decoded', payload) +}; + +// the WebSocket main handler + + +/** + * under extremely circumstances we might not even have a resolverName, then + * we issue a global error for the developer to catch it + * @param {object} ee event emitter + * @param {string} namespace nsp + * @param {string} resolverName resolver + * @param {object} json decoded payload or error object + * @param {string} ERROR_EVT_NAME the error event name + * @return {undefined} nothing return + */ +var errorTypeHandler = function (ee, namespace, resolverName, json, ERROR_EVT_NAME) { + var evt = [namespace]; + if (resolverName) { + evt.push(resolverName); + } + evt.push(ERROR_EVT_NAME); + var evtName = Reflect.apply(createEvt$1, null, evt); + // test if there is a data field + var payload = json.data || json; + ee.$trigger(evtName, [payload]); +}; + +/** + * Binding the even to socket normally + * @param {string} namespace + * @param {object} ws the nsp + * @param {object} ee EventEmitter + * @param {boolean} isPrivate to id if this namespace is private or not + * @param {object} opts configuration + * @return {object} promise resolve after the onopen event + */ +function wsMainHandler(namespace, ws, ee, isPrivate, opts) { + var useCallbackStyle = opts.useCallbackStyle; + var log = opts.log; + + log("wsMainHandler log test"); + + var READY_EVT_NAME = useCallbackStyle ? READY_PROP_NAME : ON_READY_PROP_NAME$1; + var LOGIN_EVT_NAME = useCallbackStyle ? LOGIN_PROP_NAME : ON_LOGIN_PROP_NAME$1; + var MESSAGE_EVT_NAME = useCallbackStyle ? MESSAGE_PROP_NAME : ON_MESSAGE_PROP_NAME$1; + var RESULT_EVT_NAME = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME$1; + var ERROR_EVT_NAME = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME$1; + // connection open + ws.onopen = function onOpenCallback() { + log('ws.onopen listened'); + // we just call the onReady + ee.$call(READY_EVT_NAME, namespace); + // need an extra parameter here to id the private nsp + if (isPrivate) { + log(("isPrivate and fire the " + LOGIN_EVT_NAME)); + ee.$call(LOGIN_EVT_NAME, namespace); + } + // add listener only after the open is called + ee.$only( + createEvt$1(namespace, EMIT_REPLY_TYPE$1), + function wsMainOnEvtHandler(resolverName, args) { + log('calling server', resolverName, args); + ws.send( + createQueryStr(resolverName, args) + ); + } + ); + }; + + // reply + // If we change it to the event callback style + // then the payload will just be the payload and fucks up the extractWsPayload call @TODO + ws.onmessage = function onMessageCallback(payload) { + // console.log(`on.message`, typeof payload, payload) + try { + var json = extractWsPayload(payload); + var resolverName = json.resolverName; + var type = json.type; + log('Hear from server', type, json); + switch (type) { + case EMIT_REPLY_TYPE$1: + var e1 = createEvt$1(namespace, resolverName, MESSAGE_EVT_NAME); + var r = ee.$trigger(e1, [json]); + log("EMIT_REPLY_TYPE", e1, r); + break; + case ACKNOWLEDGE_REPLY_TYPE: + var e2 = createEvt$1(namespace, resolverName, RESULT_EVT_NAME); + var x = ee.$trigger(e2, [json]); + // log(`ACKNOWLEDGE_REPLY_TYPE`, e2, json) + break; + case ERROR_TYPE: + // this is handled error and we won't throw it + // we need to extract the error from json + log("ERROR_TYPE"); + errorTypeHandler(ee, namespace, resolverName, json, ERROR_EVT_NAME); + break; + // @TODO there should be an error type instead of roll into the other two types? TBC + default: + // if this happen then we should throw it and halt the operation all together + log('Unhandled event!', json); + errorTypeHandler(ee, namespace, resolverName, json, ERROR_EVT_NAME); + // let error = {error: {'message': 'Unhandled event!', type}}; + // ee.$trigger(createEvt(namespace, resolverName, ON_RESULT_PROP_NAME), [error]) + } + } catch(e) { + console.error("ws.onmessage error", e); + errorTypeHandler(ee, namespace, false, e, ERROR_EVT_NAME); + } + }; + // when the server close the connection + ws.onclose = function onCloseCallback() { + log('ws.onclose callback'); + // @TODO what to do with this + // ee.$trigger(LOGOUT_EVENT_NAME, [namespace]) + }; + // listen to the LOGOUT_EVENT_NAME + ee.$on(LOGOUT_EVENT_NAME$1, function closeEvtHandler() { + try { + log('terminate ws connection'); + ws.terminate(); + } catch(e) { + console.error('ws.terminate error', e); + } + }); +} + +// actually binding the event client to the socket client + +/** + * 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 createNsps = function(opts, nspMap, token) { + var nspSet = nspMap.nspSet; + var publicNamespace = nspMap.publicNamespace; + var login = false; + var namespaces = []; + var nsps = {}; + // first we need to binding all the events handler + if (opts.enableAuth) { // && opts.useJwt + login = true; // just saying we need to listen to login event + namespaces = getNamespaceInOrder(nspSet, publicNamespace); + nsps = namespaces.map(function (namespace, i) { + var obj, obj$1, obj$2; + + if (i === 0) { + if (token) { + opts.token = token; + // console.log('create createNspAuthClient at run time', opts) + 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); }, {}); + } else { + var namespace = getNameFromPayload(nspSet); + namespaces.push(namespace); + // standard without login + // the stock version should not have a namespace + nsps[namespace] = createNspClient(false, opts); + } + // return + return { nsps: nsps, namespaces: namespaces, login: login } +}; + +/** + * create a ws client + * @param {object} opts configuration + * @param {object} nspMap namespace with resolvers + * @param {object} ee EventEmitter to pass through + * @return {object} what comes in what goes out + */ +function createClient(opts, nspMap, ee) { + // arguments that don't change + var args = [opts, nspMap, ee, wsMainHandler]; + // now create the nsps + var token = opts.token; + var log = opts.log; + var ref = createNsps(opts, nspMap, token); + var nsps = ref.nsps; + var namespaces = ref.namespaces; + var login = ref.login; + // 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.concat([namespaces, nsps])); + // setup listener + if (login) { + ee.$only(LOGIN_EVENT_NAME$1, function loginEventHandler(tokenLater) { + + log('createClient LOGIN_EVENT_NAME'); + + // debugFn(`LOGIN_EVENT_NAME called with token:`, tokenLater) + // @BUG this keep causing an "Disconnect call failed TypeError: Cannot read property 'readyState' of null" + // I think that is because it's not login then it can not be disconnect + // how do we track this state globally + // disconnect(nsps, JS_WS_NAME) + + // @TODO should we trigger error on this one? + // triggerNamespacesOnError(ee, namespaces, LOGIN_EVENT_NAME) + clearMainEmitEvt(ee, namespaces); + // console.log('LOGIN_EVENT_NAME', token) + var newNsps = createNsps(opts, nspMap, tokenLater); + // rebind it + Reflect.apply( + clientEventHandler, + null, + args.concat([newNsps.namespaces, newNsps.nsps]) + ); + }); + } + // return what input + return { opts: opts, nspMap: nspMap, ee: ee } +} + +// share method to create the wsClientResolver + +/** + * combine the create client resolver + * @param {object} ws the different WebSocket module + * @return {function} the wsClientResolver + */ +function createClientResolver(ws) { + var client = createWsClient(ws); + var authClient = createWsClient(ws, true); + /** + * wsClientResolver + * @param {object} opts configuration + * @param {object} nspMap from the contract + * @param {object} ee instance of the eventEmitter + * @return {object} passing the same 3 input out with additional in the opts + */ + return function(opts, nspMap, ee) { + opts.nspClient = client; + opts.nspAuthClient = authClient; + // @1.0.7 remove later once everything fixed + var log = opts.log; + if (log && typeof log === 'function') { + log('@jsonql/ws ee', ee.name); + log('@jsonql/ws createClientResolver', opts); + } + // console.log(`contract`, opts.contract) + return createClient(opts, nspMap, ee) + } +} + +// this will be the news style interface that will pass to the jsonql-ws-client + +/** + * @param {object} opts configuration + * @param {object} nspMap from the contract + * @param {object} ee instance of the eventEmitter + * @return {object} passing the same 3 input out with additional in the opts + */ +var wsClientResolver = createClientResolver(WebSocket); + +// this is the module entry point for node + +// export back the function and that's it +function wsBrowserClient(config, constProps) { + if ( config === void 0 ) config = {}; + if ( constProps === void 0 ) constProps = {}; + + var initMethod = wsClientCore(wsClientResolver, wsClientAppProps, Object.assign(wsClientConstProps, constProps)); + return initMethod(config) +} + +module.exports = wsBrowserClient; //# sourceMappingURL=main.js.map diff --git a/packages/@jsonql/ws/main.js.map b/packages/@jsonql/ws/main.js.map index aee0a927..411b13e4 100644 --- a/packages/@jsonql/ws/main.js.map +++ b/packages/@jsonql/ws/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","sources":[],"sourcesContent":[],"names":[],"mappings":""} \ 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/lodash-es/_arrayFilter.js","../../ws-client-core/node_modules/lodash-es/_createBaseFor.js","../../ws-client-core/node_modules/lodash-es/_baseTimes.js","../../ws-client-core/node_modules/lodash-es/stubFalse.js","../../ws-client-core/node_modules/lodash-es/_isIndex.js","../../ws-client-core/node_modules/lodash-es/isLength.js","../../ws-client-core/node_modules/lodash-es/_baseUnary.js","../../ws-client-core/node_modules/lodash-es/_isPrototype.js","../../ws-client-core/node_modules/lodash-es/isObject.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/_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/_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/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/identity.js","../../ws-client-core/node_modules/lodash-es/_baseProperty.js","../../ws-client-core/node_modules/jsonql-params-validator/src/object.js","../../ws-client-core/node_modules/jsonql-errors/src/500-error.js","../../ws-client-core/node_modules/jsonql-errors/src/resolver-not-found-error.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-errors/src/server-error.js","../../ws-client-core/node_modules/jsonql-params-validator/src/validator.js","../../ws-client-core/node_modules/lodash-es/_copyArray.js","../../ws-client-core/node_modules/lodash-es/_safeGet.js","../../ws-client-core/node_modules/lodash-es/_nativeKeysIn.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/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/log.js","../../ws-client-core/node_modules/nb-event-service/src/hash-code.js","../../ws-client-core/node_modules/nb-event-service/src/suspend.js","../../ws-client-core/node_modules/nb-event-service/src/store-service.js","../../ws-client-core/node_modules/nb-event-service/src/event-service.js","../../ws-client-core/node_modules/nb-event-service/index.js","../../ws-client-core/src/utils/ee.js","../../ws-client-core/node_modules/jsonql-utils/src/generic.js","../../ws-client-core/node_modules/jsonql-utils/src/contract.js","../../ws-client-core/src/options/constants.js","../../ws-client-core/src/utils/process-contract.js","../../ws-client-core/src/utils/helpers.js","../../ws-client-core/src/core/setup-auth-methods.js","../../ws-client-core/src/core/respond-handler.js","../../ws-client-core/src/core/action-call.js","../../ws-client-core/src/core/setup-resolver.js","../../ws-client-core/src/core/resolver-methods.js","../../ws-client-core/src/core/generator.js","../../ws-client-core/src/options/index.js","../../ws-client-core/src/api.js","src/options/index.js","src/core/create-ws-client.js","node_modules/lodash-es/isArray.js","node_modules/lodash-es/_objectToString.js","node_modules/lodash-es/isObjectLike.js","node_modules/lodash-es/_arrayMap.js","node_modules/lodash-es/_baseSlice.js","node_modules/lodash-es/_baseFindIndex.js","node_modules/lodash-es/_baseIsNaN.js","node_modules/lodash-es/_strictIndexOf.js","node_modules/lodash-es/_asciiToArray.js","node_modules/lodash-es/_hasUnicode.js","node_modules/lodash-es/_unicodeToArray.js","node_modules/jsonql-utils/src/generic.js","node_modules/jsonql-errors/src/validation-error.js","node_modules/jsonql-utils/src/contract.js","node_modules/jsonql-utils/src/timestamp.js","node_modules/jsonql-utils/src/params-api.js","node_modules/jsonql-ws-client-core/src/options/constants.js","node_modules/jsonql-ws-client-core/src/share/create-nsp-client.js","node_modules/jsonql-params-validator/src/string.js","node_modules/jsonql-params-validator/index.js","node_modules/nb-event-service/src/suspend.js","node_modules/jsonql-ws-client-core/src/utils/helpers.js","node_modules/jsonql-ws-client-core/src/share/trigger-namespaces-on-error.js","node_modules/jsonql-ws-client-core/src/share/client-event-handler.js","src/core/extract-ws-payload.js","src/core/ws-main-handler.js","src/core/create-client.js","src/core/create-client-resolver.js","src/node-ws-client-resolver.js","src/node.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\nexport const ARGS_NOT_ARRAY_ERR = `args is not an array! You might want to do: ES6 Array.from(arguments) or ES5 Array.prototype.slice.call(arguments)`;\nexport const PARAMS_NOT_ARRAY_ERR = `params is not an array! Did something gone wrong when you generate the contract.json?`;\nexport const EXCEPTION_CASE_ERR = 'Could not understand your arguments and parameter structure!';\nexport const UNUSUAL_CASE_ERR = 'This is an unusual situation where the arguments are more than the params, but not mark as spread';\n\n// re-export\nimport * as JSONQL_CONSTANTS from 'jsonql-constants';\n// @TODO the jsdoc return array. and we should also allow array syntax\nexport const DEFAULT_TYPE = JSONQL_CONSTANTS.DEFAULT_TYPE;\nexport const ARRAY_TYPE_LFT = JSONQL_CONSTANTS.ARRAY_TYPE_LFT;\nexport const ARRAY_TYPE_RGT = JSONQL_CONSTANTS.ARRAY_TYPE_RGT;\n\nexport const TYPE_KEY = JSONQL_CONSTANTS.TYPE_KEY;\nexport const OPTIONAL_KEY = JSONQL_CONSTANTS.OPTIONAL_KEY;\nexport const ENUM_KEY = JSONQL_CONSTANTS.ENUM_KEY;\nexport const ARGS_KEY = JSONQL_CONSTANTS.ARGS_KEY;\nexport const CHECKER_KEY = JSONQL_CONSTANTS.CHECKER_KEY;\nexport const ALIAS_KEY = JSONQL_CONSTANTS.ALIAS_KEY;\n\nexport const ARRAY_TYPE = JSONQL_CONSTANTS.ARRAY_TYPE;\nexport const OBJECT_TYPE = JSONQL_CONSTANTS.OBJECT_TYPE;\nexport const STRING_TYPE = JSONQL_CONSTANTS.STRING_TYPE;\nexport const BOOLEAN_TYPE = JSONQL_CONSTANTS.BOOLEAN_TYPE;\nexport const NUMBER_TYPE = JSONQL_CONSTANTS.NUMBER_TYPE;\nexport const KEY_WORD = JSONQL_CONSTANTS.KEY_WORD;\nexport const OR_SEPERATOR = JSONQL_CONSTANTS.OR_SEPERATOR;\n\n// not actually in use\n// export const NUMBER_TYPES = JSONQL_CONSTANTS.NUMBER_TYPES;\n","// primitive types\nimport checkIsNumber from './number'\nimport checkIsString from './string'\nimport checkIsBoolean from './boolean'\nimport checkIsAny from './any'\nimport { NUMBER_TYPE, STRING_TYPE, BOOLEAN_TYPE } from './constants'\n\n/**\n * this is a wrapper method to call different one based on their type\n * @param {string} type to check\n * @return {function} a function to handle the type\n */\nconst combineFn = function(type) {\n switch (type) {\n case NUMBER_TYPE:\n return checkIsNumber;\n case STRING_TYPE:\n return checkIsString;\n case BOOLEAN_TYPE:\n return checkIsBoolean;\n default:\n return checkIsAny;\n }\n}\n\nexport default combineFn\n","// validate array type\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","/**\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 * 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 * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\nexport default baseTimes;\n","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n return false;\n}\n\nexport default stubFalse;\n","/** 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","/** 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 * 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","/** 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 the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nexport default isObject;\n","/**\n * 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","/** 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","/** 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 * 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 * 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 * 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","// validate object type\n\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport filter from 'lodash-es/filter'\n\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","/**\n * This is a custom error to throw when server throw a 500\n * This help us to capture the right error, due to the call happens in sequence\n * @param {string} message to tell what happen\n * @param {mixed} extra things we want to add, 500?\n */\nexport default class Jsonql500Error extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = Jsonql500Error.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, Jsonql500Error)\n }\n }\n\n static get statusCode() {\n return 500;\n }\n\n static get name() {\n return 'Jsonql500Error';\n }\n\n}\n","/**\n * This is a custom error to throw when could not find the resolver\n * This help us to capture the right error, due to the call happens in sequence\n * @param {string} message to tell what happen\n * @param {mixed} extra things we want to add, 500?\n */\nexport default class JsonqlResolverNotFoundError extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlResolverNotFoundError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlResolverNotFoundError);\n }\n }\n\n static get statusCode() {\n return 404;\n }\n\n static get name() {\n return 'JsonqlResolverNotFoundError';\n }\n}\n","// this get throw from within the checkOptions when run through the enum failed\nexport default class JsonqlEnumError extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlEnumError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlEnumError);\n }\n }\n\n static get name() {\n return 'JsonqlEnumError';\n }\n}\n","// this will throw from inside the checkOptions\nexport default class JsonqlTypeError extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlTypeError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlTypeError);\n }\n }\n\n static get name() {\n return 'JsonqlTypeError';\n }\n}\n","// allow supply a custom checker function\n// if that failed then we throw this error\nexport default class JsonqlCheckerError extends Error {\n constructor(...args) {\n super(...args)\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlCheckerError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlCheckerError)\n }\n }\n\n static get name() {\n return 'JsonqlCheckerError';\n }\n}\n","// custom validation error class\n// when validaton failed\nexport default class JsonqlValidationError extends Error {\n constructor(...args) {\n super(...args)\n\n this.message = args[0]\n this.detail = args[1]\n\n this.className = JsonqlValidationError.name;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, JsonqlValidationError)\n }\n }\n\n static get name() {\n return 'JsonqlValidationError';\n }\n}\n","// this is from an example from Koa team to use for internal middleware ctx.throw\n// but after the test the res.body part is unable to extract the required data\n// I keep this one here for future reference\n\nexport default class JsonqlServerError extends Error {\n\n constructor(statusCode, message) {\n super(message)\n this.statusCode = statusCode;\n this.className = JsonqlServerError.name;\n }\n\n static get name() {\n return 'JsonqlServerError';\n }\n}\n","// 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 checkIsObject,\n combineFn,\n notEmpty\n} from './index'\nimport {\n DEFAULT_TYPE,\n ARRAY_TYPE,\n OBJECT_TYPE,\n ARGS_NOT_ARRAY_ERR,\n PARAMS_NOT_ARRAY_ERR,\n EXCEPTION_CASE_ERR,\n UNUSUAL_CASE_ERR\n} from './constants'\nimport { DATA_KEY, ERROR_KEY } from 'jsonql-constants'\nimport { JsonqlError } from 'jsonql-errors'\n// 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 JsonqlError(PARAMS_NOT_ARRAY_ERR)\n }\n if (params.length === 0) {\n return [];\n }\n if (!checkIsArray(args)) {\n throw new JsonqlError(ARGS_NOT_ARRAY_ERR)\n }\n // debugFn(args, params);\n // fall through switch\n switch(true) {\n case args.length == params.length: // standard\n return args.map((arg, i) => (\n {\n arg,\n index: i,\n param: params[i]\n }\n ))\n case params[0].variable === true: // using spread syntax\n const type = params[0].type;\n return args.map((arg, i) => (\n {\n arg,\n index: i, // keep the index for reference\n param: params[i] || { type, name: '_' }\n }\n ))\n // with optional defaultValue parameters\n case args.length < params.length:\n return params.map((param, i) => (\n {\n param,\n index: i,\n arg: getOptionalValue(args[i], param),\n optional: param.optional || false\n }\n ))\n // this one pass more than it should have anything after the args.length will be cast as any type\n case args.length > params.length:\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 * 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","/**\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 * 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 * 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","/** 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'\nimport 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'\n// PIA syntax\nexport const isObject = checkIsObject;\nexport const isAny = checkIsAny;\nexport const isString = checkIsString;\nexport const isBoolean = checkIsBoolean;\nexport const isNumber = checkIsNumber;\nexport const isArray = checkIsArray;\nexport const isNotEmpty = notEmpty;\n\nimport * as validator from './src/validator'\n\nexport const normalizeArgs = validator.normalizeArgs;\nexport const validateSync = validator.validateSync;\nexport const validateAsync = validator.validateAsync;\n\n// configuration checking\n\nimport * as jsonqlOptions from './src/options'\n\nexport const JSONQL_PARAMS_VALIDATOR_INFO = jsonqlOptions.JSONQL_PARAMS_VALIDATOR_INFO;\n\nexport const createConfig = jsonqlOptions.createConfig;\nexport const constructConfig = jsonqlOptions.constructConfigFn;\n// construct the final output 1.5.2\nexport const checkConfigAsync = jsonqlOptions.getCheckConfigAsync(validator.validateSync)\nexport const checkConfig = jsonqlOptions.getCheckConfig(validator.validateSync)\n\n// export the two extra functions\nimport isInArray from './src/is-in-array'\nimport isObjectHasKeyFn from './src/options/is-key-in-object'\n\nexport const inArray = isInArray;\nexport const isObjectHasKey = isObjectHasKeyFn;\n","// move the get logger stuff here\n/**\n * @TODO remove this implmenetation once the test is done\n */\nconst dummyLogger = (...args) => {\n Reflect.apply(console.info, console, ['[jsonql-ws-client-core]', ...args])\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 opts.log = dummyLogger\n }\n opts.log('--- wsClientCore config opts ---', opts)\n return opts\n}\n\nexport { getLogFn }","/**\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// wrapper to make sure it string \nexport function hashCode2Str(s) {\n return hashCode(s) + ''\n}\n","// making all the functionality on it's own\n// import { WatchClass } from './watch'\n\nexport default class SuspendClass {\n\n constructor() {\n // suspend, release and queue\n this.__suspend__ = null;\n this.queueStore = new Set()\n /*\n this.watch('suspend', function(value, prop, oldValue) {\n this.logger(`${prop} set from ${oldValue} to ${value}`)\n // it means it set the suspend = true then release it\n if (oldValue === true && value === false) {\n // we want this happen after the return happens\n setTimeout(() => {\n this.release()\n }, 1)\n }\n return value; // we need to return the value to store it\n })\n */\n }\n\n /**\n * setter to set the suspend and check if it's boolean value\n * @param {boolean} value to trigger\n */\n set $suspend(value) {\n if (typeof value === 'boolean') {\n const lastValue = this.__suspend__;\n this.__suspend__ = value;\n this.logger('($suspend)', `Change from ${lastValue} --> ${value}`)\n if (lastValue === true && value === false) {\n setTimeout(() => {\n this.release()\n }, 1)\n }\n } else {\n throw new Error(`$suspend only accept Boolean value!`)\n }\n }\n\n /**\n * queuing call up when it's in suspend mode\n * @param {any} value\n * @return {Boolean} true when added or false when it's not\n */\n $queue(...args) {\n if (this.__suspend__ === true) {\n this.logger('($queue)', 'added to $queue', args)\n // there shouldn't be any duplicate ...\n this.queueStore.add(args)\n }\n return this.__suspend__;\n }\n\n /**\n * a getter to get all the store queue\n * @return {array} Set turn into Array before return\n */\n get $queues() {\n let size = this.queueStore.size;\n this.logger('($queues)', `size: ${size}`)\n if (size > 0) {\n return Array.from(this.queueStore)\n }\n return []\n }\n\n /**\n * Release the queue\n * @return {int} size if any\n */\n release() {\n let size = this.queueStore.size\n this.logger('(release)', `Release was called ${size}`)\n if (size > 0) {\n const queue = Array.from(this.queueStore)\n this.queueStore.clear()\n this.logger('queue', queue)\n queue.forEach(args => {\n this.logger(args)\n Reflect.apply(this.$trigger, this, args)\n })\n this.logger(`Release size ${this.queueStore.size}`)\n }\n }\n}\n","// break up the main file because its getting way too long\nimport {\n NB_EVENT_SERVICE_PRIVATE_STORE,\n NB_EVENT_SERVICE_PRIVATE_LAZY\n} from './store'\nimport { hashCode2Str } from './hash-code'\nimport SuspendClass from './suspend'\n\nexport default class NbEventServiceBase extends SuspendClass {\n\n constructor(config = {}) {\n super()\n if (config.logger && typeof config.logger === 'function') {\n this.logger = config.logger;\n }\n this.keep = config.keep;\n // for the $done setter\n this.result = config.keep ? [] : null;\n // we need to init the store first otherwise it could be a lot of checking later\n this.normalStore = new Map()\n this.lazyStore = new Map()\n }\n\n // for id if the instance is this class\n get is() {\n return 'nb-event-service'\n }\n\n /**\n * validate the event name(s)\n * @param {string[]} evt event name\n * @return {boolean} true when OK\n */\n validateEvt(...evt) {\n evt.forEach(e => {\n if (typeof e !== 'string') {\n this.logger('(validateEvt)', e)\n throw new Error(`event name must be string type!`)\n }\n })\n return true;\n }\n\n /**\n * Simple quick check on the two main parameters\n * @param {string} evt event name\n * @param {function} callback function to call\n * @return {boolean} true when OK\n */\n validate(evt, callback) {\n if (this.validateEvt(evt)) {\n if (typeof callback === 'function') {\n return true;\n }\n }\n throw new Error(`callback required to be function type!`)\n }\n\n /**\n * Check if this type is correct or not added in V1.5.0\n * @param {string} type for checking\n * @return {boolean} true on OK\n */\n validateType(type) {\n const types = ['on', 'only', 'once', 'onlyOnce']\n return !!types.filter(t => type === t).length;\n }\n\n /**\n * Run the callback\n * @param {function} callback function to execute\n * @param {array} payload for callback\n * @param {object} ctx context or null\n * @return {void} the result store in $done\n */\n run(callback, payload, ctx) {\n this.logger('(run)', callback, payload, ctx)\n this.$done = Reflect.apply(callback, ctx, this.toArray(payload))\n }\n\n /**\n * Take the content out and remove it from store id by the name\n * @param {string} evt event name\n * @param {string} [storeName = lazyStore] name of store\n * @return {object|boolean} content or false on not found\n */\n takeFromStore(evt, storeName = 'lazyStore') {\n let store = this[storeName] // it could be empty at this point\n if (store) {\n this.logger('(takeFromStore)', storeName, store)\n if (store.has(evt)) {\n let content = store.get(evt)\n this.logger('(takeFromStore)', `has ${evt}`, content)\n store.delete(evt)\n return content;\n }\n return false;\n }\n throw new Error(`${storeName} is not supported!`)\n }\n\n /**\n * The add to store step is similar so make it generic for resuse\n * @param {object} store which store to use\n * @param {string} evt event name\n * @param {spread} args because the lazy store and normal store store different things\n * @return {array} store and the size of the store\n */\n addToStore(store, evt, ...args) {\n let fnSet;\n if (store.has(evt)) {\n this.logger('(addToStore)', `${evt} existed`)\n fnSet = store.get(evt)\n } else {\n this.logger('(addToStore)', `create new Set for ${evt}`)\n // this is new\n fnSet = new Set()\n }\n // lazy only store 2 items - this is not the case in V1.6.0 anymore\n // we need to check the first parameter is string or not\n if (args.length > 2) {\n if (Array.isArray(args[0])) { // lazy store\n // check if this type of this event already register in the lazy store\n let [,,t] = args;\n if (!this.checkTypeInLazyStore(evt, t)) {\n fnSet.add(args)\n }\n } else {\n if (!this.checkContentExist(args, fnSet)) {\n this.logger('(addToStore)', `insert new`, args)\n fnSet.add(args)\n }\n }\n } else { // add straight to lazy store\n fnSet.add(args)\n }\n store.set(evt, fnSet)\n return [store, fnSet.size]\n }\n\n /**\n * @param {array} args for compare\n * @param {object} fnSet A Set to search from\n * @return {boolean} true on exist\n */\n checkContentExist(args, fnSet) {\n let list = Array.from(fnSet)\n return !!list.filter(l => {\n let [hash,] = l;\n if (hash === args[0]) {\n return true;\n }\n return false;\n }).length;\n }\n\n /**\n * get the existing type to make sure no mix type add to the same store\n * @param {string} evtName event name\n * @param {string} type the type to check\n * @return {boolean} true you can add, false then you can't add this type\n */\n checkTypeInStore(evtName, type) {\n this.validateEvt(evtName, type)\n let all = this.$get(evtName, true)\n if (all === false) {\n // pristine it means you can add\n return true;\n }\n // it should only have ONE type in ONE event store\n return !all.filter(list => {\n let [ ,,,t ] = list;\n return type !== t;\n }).length;\n }\n\n /**\n * This is checking just the lazy store because the structure is different\n * therefore we need to use a new method to check it\n */\n checkTypeInLazyStore(evtName, type) {\n this.validateEvt(evtName, type)\n let store = this.lazyStore.get(evtName)\n this.logger('(checkTypeInLazyStore)', store)\n if (store) {\n return !!Array\n .from(store)\n .filter(l => {\n let [,,t] = l;\n return t !== type;\n }).length\n }\n return false;\n }\n\n /**\n * wrapper to re-use the addToStore,\n * V1.3.0 add extra check to see if this type can add to this evt\n * @param {string} evt event name\n * @param {string} type on or once\n * @param {function} callback function\n * @param {object} context the context the function execute in or null\n * @return {number} size of the store\n */\n addToNormalStore(evt, type, callback, context = null) {\n this.logger('(addToNormalStore)', evt, type, 'try to add to normal store')\n // @TODO we need to check the existing store for the type first!\n if (this.checkTypeInStore(evt, type)) {\n this.logger('(addToNormalStore)', `${type} can add to ${evt} normal store`)\n let key = this.hashFnToKey(callback)\n let args = [this.normalStore, evt, key, callback, context, type]\n let [_store, size] = Reflect.apply(this.addToStore, this, args)\n this.normalStore = _store;\n return size;\n }\n return false;\n }\n\n /**\n * Add to lazy store this get calls when the callback is not register yet\n * so we only get a payload object or even nothing\n * @param {string} evt event name\n * @param {array} payload of arguments or empty if there is none\n * @param {object} [context=null] the context the callback execute in\n * @param {string} [type=false] register a type so no other type can add to this evt\n * @return {number} size of the store\n */\n addToLazyStore(evt, payload = [], context = null, type = false) {\n // this is add in V1.6.0\n // when there is type then we will need to check if this already added in lazy store\n // and no other type can add to this lazy store\n let args = [this.lazyStore, evt, this.toArray(payload), context]\n if (type) {\n args.push(type)\n }\n let [_store, size] = Reflect.apply(this.addToStore, this, args)\n this.lazyStore = _store;\n return size;\n }\n\n /**\n * make sure we store the argument correctly\n * @param {*} arg could be array\n * @return {array} make sured\n */\n toArray(arg) {\n return Array.isArray(arg) ? arg : [arg];\n }\n\n /**\n * setter to store the Set in private\n * @param {object} obj a Set\n */\n set normalStore(obj) {\n NB_EVENT_SERVICE_PRIVATE_STORE.set(this, obj)\n }\n\n /**\n * @return {object} Set object\n */\n get normalStore() {\n return NB_EVENT_SERVICE_PRIVATE_STORE.get(this)\n }\n\n /**\n * setter to store the Set in lazy store\n * @param {object} obj a Set\n */\n set lazyStore(obj) {\n NB_EVENT_SERVICE_PRIVATE_LAZY.set(this , obj)\n }\n\n /**\n * @return {object} the lazy store Set\n */\n get lazyStore() {\n return NB_EVENT_SERVICE_PRIVATE_LAZY.get(this)\n }\n\n /**\n * generate a hashKey to identify the function call\n * The build-in store some how could store the same values!\n * @param {function} fn the converted to string function\n * @return {string} hashKey\n */\n hashFnToKey(fn) {\n return hashCode2Str(fn.toString())\n }\n}\n","// The top level\nimport NbStoreService from './store-service'\n// export\nexport default class EventService extends NbStoreService {\n /**\n * class constructor\n */\n constructor(config = {}) {\n super(config)\n }\n\n /**\n * logger function for overwrite\n */\n logger() {}\n\n //////////////////////////\n // PUBLIC METHODS //\n //////////////////////////\n\n /**\n * Register your evt handler, note we don't check the type here,\n * we expect you to be sensible and know what you are doing.\n * @param {string} evt name of event\n * @param {function} callback bind method --> if it's array or not\n * @param {object} [context=null] to execute this call in\n * @return {number} the size of the store\n */\n $on(evt , callback , context = null) {\n const type = 'on';\n this.validate(evt, callback)\n // first need to check if this evt is in lazy store\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register first then call later\n if (lazyStoreContent === false) {\n this.logger('($on)', `${evt} callback is not in lazy store`)\n // @TODO we need to check if there was other listener to this\n // event and are they the same type then we could solve that\n // register the different type to the same event name\n\n return this.addToNormalStore(evt, type, callback, context)\n }\n this.logger('($on)', `${evt} found in lazy store`)\n // this is when they call $trigger before register this callback\n let size = 0;\n lazyStoreContent.forEach(content => {\n let [ payload, ctx, t ] = content;\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.logger(`($on)`, `call run on ${evt}`)\n this.run(callback, payload, context || ctx)\n size += this.addToNormalStore(evt, type, callback, context || ctx)\n })\n return size;\n }\n\n /**\n * once only registered it once, there is no overwrite option here\n * @NOTE change in v1.3.0 $once can add multiple listeners\n * but once the event fired, it will remove this event (see $only)\n * @param {string} evt name\n * @param {function} callback to execute\n * @param {object} [context=null] the handler execute in\n * @return {boolean} result\n */\n $once(evt , callback , context = null) {\n this.validate(evt, callback)\n const type = 'once';\n let lazyStoreContent = this.takeFromStore(evt)\n // this is normal register before call $trigger\n let nStore = this.normalStore;\n if (lazyStoreContent === false) {\n this.logger('($once)', `${evt} not in the lazy store`)\n // v1.3.0 $once now allow to add multiple listeners\n return this.addToNormalStore(evt, type, callback, context)\n } else {\n // now this is the tricky bit\n // there is a potential bug here that cause by the developer\n // if they call $trigger first, the lazy won't know it's a once call\n // so if in the middle they register any call with the same evt name\n // then this $once call will be fucked - add this to the documentation\n this.logger('($once)', lazyStoreContent)\n const list = Array.from(lazyStoreContent)\n // should never have more than 1\n const [ payload, ctx, t ] = list[0]\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.logger('($once)', `call run for ${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 store`)\n added = this.addToNormalStore(evt, type, callback, context)\n }\n if (lazyStoreContent !== false) {\n // there are data store in lazy store\n this.logger('($only)', `${evt} found data in lazy store to execute`)\n const list = Array.from(lazyStoreContent)\n // $only allow to trigger this multiple time on the single handler\n list.forEach( l => {\n const [ payload, ctx, t ] = l;\n if (t && t !== type) {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.logger(`($only)`, `call run for ${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 store`)\n added = this.addToNormalStore(evt, type, callback, context)\n }\n if (lazyStoreContent !== false) {\n // there are data store in lazy store\n this.logger('($onlyOnce)', lazyStoreContent)\n const list = Array.from(lazyStoreContent)\n // should never have more than 1\n const [ payload, ctx, t ] = list[0]\n if (t && t !== 'onlyOnce') {\n throw new Error(`You are trying to register an event already been taken by other type: ${t}`)\n }\n this.logger(`($onlyOnce)`, `call run for ${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 // @1.8.0 to add the suspend queue\n let added = this.$queue(evt, payload, context, type)\n this.logger('($trigger)', evt, 'found; add to queue: ', added)\n if (added === true) {\n this.logger('($trigger)', evt, 'not 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 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 this.validateEvt(evt)\n let stores = [ this.lazyStore, this.normalStore ]\n let found = false;\n stores.forEach(store => {\n if (store.has(evt)) {\n found = true;\n this.logger('($off)', evt)\n store.delete(evt)\n }\n })\n return found;\n }\n\n /**\n * return all the listener from the event\n * @param {string} evtName event name\n * @param {boolean} [full=false] if true then return the entire content\n * @return {array|boolean} listerner(s) or false when not found\n */\n $get(evt, full = false) {\n this.validateEvt(evt)\n let store = this.normalStore;\n if (store.has(evt)) {\n return Array\n .from(store.get(evt))\n .map( l => {\n if (full) {\n return l;\n }\n let [key, callback, ] = l;\n return callback;\n })\n }\n return false;\n }\n\n /**\n * store the return result from the run\n * @param {*} value whatever return from callback\n */\n set $done(value) {\n this.logger('($done)', 'value: ', value)\n if (this.keep) {\n this.result.push(value)\n } else {\n this.result = value;\n }\n }\n\n /**\n * @TODO is there any real use with the keep prop?\n * getter for $done\n * @return {*} whatever last store result\n */\n get $done() {\n if (this.keep) {\n this.logger('(get $done)', this.result)\n return this.result[this.result.length - 1]\n }\n return this.result;\n }\n\n\n}\n","// default\nimport NBEventService from './src/event-service'\n\nexport default NBEventService\n","// this will generate a event emitter and will be use everywhere\nimport NBEventService from 'nb-event-service'\n// create a clone version so we know which one we actually is using\nclass JsonqlWsEvt extends NBEventService {\n\n constructor(logger) {\n if (typeof logger !== 'function') {\n throw new Error(`Just die here the logger is not a function!`)\n }\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 log(`Create a new Event Emitter`)\n return new JsonqlWsEvt( opts.log )\n}\n\nexport { getEventEmitter }\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 * @return {*} json object on success\n */\nconst parse = function(n) {\n try {\n return JSON.parse(n)\n } catch(e) {\n return n;\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 console.info('obj', obj)\n console.error(e)\n throw new Error(e)\n */\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 parse(n)\n }\n return JSON.parse(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","// 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')) {\n return contract.socket;\n }\n return false;\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 * @param {boolean} [fallback=false] this is a fall back option for old code\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, fallback = false) {\n let socket = extractSocketPart(contract)\n if (socket === false) {\n if (fallback) {\n return contract; // just return the whole contract\n }\n throw new JsonqlError(`socket not found in contract!`)\n }\n let nspSet = {};\n let size = 0;\n let publicNamespace;\n for (let resolverName in socket) {\n let params = socket[resolverName];\n let { namespace } = params;\n if (namespace) {\n if (!nspSet[namespace]) {\n ++size;\n nspSet[namespace] = {};\n }\n nspSet[namespace][resolverName] = params;\n if (!publicNamespace) {\n if (params.public) {\n publicNamespace = namespace;\n }\n }\n }\n }\n return { size, nspSet, publicNamespace }\n}\n\n/**\n * @NOTE ported from jsonql-ws-client\n * Got to make sure the connection order otherwise\n * it will hang\n * @param {object} nspSet contract\n * @param {string} publicNamespace like the name said\n * @return {array} namespaces in order\n */\nexport function getNamespaceInOrder(nspSet, publicNamespace) {\n let names = []; // need to make sure the order!\n for (let namespace in nspSet) {\n if (namespace === publicNamespace) {\n names[1] = namespace;\n } else {\n names[0] = namespace;\n }\n }\n return names;\n}\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","// constants\n\nimport {\n EMIT_REPLY_TYPE,\n JS_WS_SOCKET_IO_NAME,\n JS_WS_NAME,\n ON_MESSAGE_PROP_NAME,\n ON_RESULT_PROP_NAME\n} from 'jsonql-constants'\n\nconst SOCKET_IO = JS_WS_SOCKET_IO_NAME;\nconst WS = JS_WS_NAME;\n\nconst AVAILABLE_SERVERS = [SOCKET_IO, WS]\n\nconst SOCKET_NOT_DEFINE_ERR = 'socket is not define in the contract file!';\n\nconst SERVER_NOT_SUPPORT_ERR = 'is not supported server name!';\n\nconst MISSING_PROP_ERR = 'Missing property in contract!';\n\nconst UNKNOWN_CLIENT_ERR = 'Unknown client type!';\n\nconst EMIT_EVT = EMIT_REPLY_TYPE;\n\nconst NAMESPACE_KEY = 'namespaceMap';\n\nconst UNKNOWN_RESULT = 'UKNNOWN RESULT!';\n\nconst NOT_ALLOW_OP = 'This operation is not allow!';\n\nconst MY_NAMESPACE = 'myNamespace'\n\nconst CB_FN_NAME = 'on'\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_PROP_NAME,\n ON_RESULT_PROP_NAME,\n NAMESPACE_KEY,\n UNKNOWN_RESULT,\n NOT_ALLOW_OP,\n MY_NAMESPACE,\n CB_FN_NAME\n}\n","// mapping the resolver to their respective nsp\nimport { JSONQL_PATH, NSP_SET, PUBLIC_NAMESPACE } from 'jsonql-constants'\nimport { groupByNamespace, extractSocketPart } from 'jsonql-utils/module'\nimport { JsonqlResolverNotFoundError } from 'jsonql-errors'\n\nimport { MISSING_PROP_ERR } from '../options/constants'\n\n/**\n * Just make sure the object contain what we are looking for\n * @param {object} opts configuration from checkOptions\n * @return {object} the target content\n */\nconst getResolverList = contract => {\n const result = extractSocketPart(contract)\n if (result !== false) {\n return result\n }\n throw new JsonqlResolverNotFoundError(MISSING_PROP_ERR)\n}\n\n/**\n * process the contract first\n * @param {object} opts configuration\n * @return {object} sorted list\n */\nexport default function processContract(opts) {\n const { contract, enableAuth } = opts\n if (enableAuth) {\n return groupByNamespace(contract)\n }\n return {\n [NSP_SET]: { [JSONQL_PATH]: getResolverList(contract) },\n [PUBLIC_NAMESPACE]: JSONQL_PATH\n }\n}\n","// group all the small functions here\nimport { JS_WS_SOCKET_IO_NAME, JS_WS_NAME, EMIT_REPLY_TYPE } from 'jsonql-constants'\nimport { toArray, createEvt } from 'jsonql-utils/src/generic'\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\n// we shouldn't do this anymore\nexport const fixWss = (url, serverType) => {\n // ws only allow ws:// path\n if (serverType === JS_WS_NAME) {\n return url.replace('http://', 'ws://')\n }\n return url\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 * @param {object} nsps namespace as key\n * @param {string} type of server\n */\nexport const disconnect = (nsps, type = JS_WS_SOCKET_IO_NAME) => {\n try {\n // @TODO need to figure out a better way here?\n const method = type === JS_WS_SOCKET_IO_NAME ? 'disconnect' : 'terminate';\n for (let namespace in nsps) {\n let nsp = nsps[namespace]\n if (nsp && nsp[method]) {\n Reflect.apply(nsp[method], null, [])\n }\n }\n } catch(e) {\n // socket.io throw a this.destroy of undefined?\n console.error('Disconnect call failed', e)\n }\n}\n","// take out from the resolver-methods\nimport { \n LOGIN_EVENT_NAME, \n LOGOUT_EVENT_NAME, \n ON_LOGIN_PROP_NAME\n} from 'jsonql-constants'\nimport { JsonqlValidationError } from 'jsonql-errors'\nimport { injectToFn, chainFns, isString } 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 * 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 ]\n */\nconst setupLoginHandler = (obj, opts, ee) => [\n injectToFn(obj, opts.loginHandlerName, function loginHandler(token) {\n if (token && isString(token)) {\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 ee,\n opts\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, ee ]\n */\nconst setupLogoutHandler = (obj, opts, ee) => [\n injectToFn(obj, opts.logoutHandlerName, function logoutHandler(...args) {\n ee.$trigger(LOGOUT_EVENT_NAME, args)\n }),\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 {object} obj with onLogin prop\n */\nexport function createOnLoginhandler(obj, ee) {\n return objDefineProps(obj, ON_LOGIN_PROP_NAME, function onLoginCallbackHandler(onLoginCallback) {\n if (isFunc(onLoginCallback)) {\n // only one callback can registered with it, TBC\n ee.$only(ON_LOGIN_PROP_NAME, onLoginCallback)\n }\n })\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 {object} obj with auth methods if any\n */\nexport function createAuthMethods(obj, opts, ee) {\n return chainFns(\n setupLoginHandler, \n setupLogoutHandler,\n createOnLoginhandler\n )(obj, opts, ee)\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_PROP_NAME, RESULT_PROP_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 * @return {void} nothing\n */\nexport function actionCall(ee, namespace, resolverName, args = []) {\n const eventName = createEvt(namespace, EMIT_REPLY_TYPE)\n // const RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME\n \n debugFn(`actionCall: ${eventName} --> ${resolverName}`, args)\n // this could be a problem\n ee.$trigger(eventName, [resolverName, toArray(args)])\n\n // then we need to listen to the event callback here as well\n return new Promise((resolver, rejecter) => {\n ee.$on(\n createEvt(namespace, resolverName, ON_RESULT_PROP_NAME),\n function actionCallResultHandler(result) {\n \n debugFn(`got the first result`, result)\n \n respondHandler(result, resolver, rejecter)\n }\n )\n })\n}\n","// break up the original setup resolver method here\n// import { JsonqlValidationError, finalCatch } from 'jsonql-errors'\nimport {\n ON_ERROR_PROP_NAME,\n ON_MESSAGE_PROP_NAME,\n ON_RESULT_PROP_NAME\n} from 'jsonql-constants'\nimport { MY_NAMESPACE } from '../options/constants'\nimport { chainFns, objDefineProps, injectToFn, createEvt, isFunc } from '../utils'\n\nimport { respondHandler } from './respond-handler'\nimport { setupSend } from './setup-send'\n\n/**\n * The first one in the chain\n * @return {array}\n */\nconst setupNamespace = (fn, ee, namespace, resolverName, params) => [\n injectToFn(fn, MY_NAMESPACE, namespace),\n ee,\n namespace,\n resolverName,\n params\n]\n\n// onResult handler\nconst setupOnResult = (fn, ee, namespace, resolverName, params) => [\n objDefineProps(fn, ON_RESULT_PROP_NAME, function(resultCallback) {\n if (isFunc(resultCallback)) {\n ee.$on(\n createEvt(namespace, resolverName, ON_RESULT_PROP_NAME),\n function resultHandler(result) {\n respondHandler(result, resultCallback, (error) => {\n ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error)\n })\n }\n )\n }\n }),\n ee,\n namespace,\n resolverName,\n params\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\nconst setupOnMessage = (fn, ee, namespace, resolverName, params) => [\n objDefineProps(fn, ON_MESSAGE_PROP_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 ee.$trigger(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), error)\n })\n }\n // register the handler for this message event\n ee.$only(createEvt(namespace, resolverName, ON_MESSAGE_PROP_NAME), onMessageCallback)\n }\n }),\n ee,\n namespace,\n resolverName,\n params\n]\n\n// add an ON_ERROR_PROP_NAME handler\nconst setupOnError = (fn, ee, namespace, resolverName, params) => [\n objDefineProps(fn, ON_ERROR_PROP_NAME, function(resolverErrorHandler) {\n if (isFunc(resolverErrorHandler)) {\n // please note ON_ERROR_PROP_NAME can add multiple listners\n ee.$only(createEvt(namespace, resolverName, ON_ERROR_PROP_NAME), resolverErrorHandler)\n }\n }),\n ee,\n namespace,\n resolverName,\n params\n]\n\n/**\n * Add extra property to the resolver\n * @param {string} namespace where this belongs\n * @param {string} resolverName name as event name\n * @param {object} params from contract\n * @param {function} fn resolver function\n * @param {object} ee EventEmitter\n * @return {function} resolver\n */\nexport function setupResolver(namespace, resolverName, params, fn, ee) {\n // also need to setup a getter to get back the namespace of this resolver\n let args = [setupNamespace]\n args.push(setupOnResult, setupOnMessage, setupOnError)\n args.push(setupSend)\n // get the executor\n const executor = Reflect.apply(chainFns, null, args)\n\n return Reflect.apply(executor, null, [fn, ee, namespace, resolverName, params])\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 { createEvt, objDefineProps, isFunc, injectToFn } from '../utils'\nimport {\n ON_ERROR_PROP_NAME,\n ON_READY_PROP_NAME\n} from 'jsonql-constants'\n// import { CB_FN_NAME } from '../options/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 * @return {function} resolver\n */\nfunction createResolver(ee, namespace, resolverName, params) {\n // note we pass the new withResult=true option\n return function(...args) {\n return validateAsync(args, params.params, true)\n .then(_args => actionCall(ee, namespace, resolverName, _args))\n .catch(finalCatch)\n }\n}\n\n/**\n * step one get the obj map with the namespace\n * @param {object} opts configuration\n * @param {object} ee EventEmitter\n * @param {object} nspSet resolvers index by their namespace\n * @return {promise} resolve the obj mapped, and start the chain\n */\nexport function generateResolvers(opts, ee, nspSet) {\n let obj = {}\n // const { useCallbackStyle } = opts; // @1.2.1\n for (let namespace in nspSet) {\n let list = nspSet[namespace]\n for (let resolverName in list) {\n // resolverNames.push(resolverName)\n let params = list[resolverName]\n let fn = createResolver(ee, namespace, resolverName, params)\n // this should set as a getter therefore can not be overwrite by accident\n // obj[resolverName] = setupResolver(namespace, resolverName, params, fn, ee)\n obj = injectToFn(obj, resolverName, setupResolver(namespace, resolverName, params, fn, ee))\n }\n }\n // resolve the obj to start the chain\n // chain the result to allow the chain processing\n return [ obj, opts, ee, nspSet ]\n}\n\n/**\n * The problem is the namespace can have more than one\n * and we only have on onError message\n * @param {object} obj the client itself\n * @param {object} opts configuration\n * @param {object} ee Event Emitter\n * @param {object} nspSet namespace keys\n * @return {array} [obj, opts, ee] \n */\nexport function createNamespaceErrorHandler(obj, opts, ee, nspSet) {\n return [\n // using the onError as name\n // @TODO we should follow the convention earlier\n // make this a setter for the obj itself\n objDefineProps(obj, ON_ERROR_PROP_NAME, function namespaceErrorCallbackHandler(namespaceErrorHandler) {\n if (isFunc(namespaceErrorHandler)) {\n // please note ON_ERROR_PROP_NAME can add multiple listners\n for (let namespace in nspSet) {\n // this one is very tricky, we need to make sure the trigger is calling\n // with the namespace as well as the error\n ee.$on(createEvt(namespace, ON_ERROR_PROP_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} obj the client itself\n * @param {object} opts configuration\n * @param {object} ee Event Emitter\n * @return {array} [ obj, opts, ee ]\n */\nexport function createOnReadyhandler(obj, opts, ee) {\n return [\n objDefineProps(obj, ON_READY_PROP_NAME, function onReadyCallbackHandler(onReadyCallback) {\n if (isFunc(onReadyCallback)) {\n // reduce it down to just one flat level\n ee.$on(ON_READY_PROP_NAME, onReadyCallback)\n }\n }),\n opts,\n ee\n ]\n}\n\n\n\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'\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 generator(opts, nspMap, ee) {\n const { nspSet } = nspMap\n const { enableAuth } = opts\n let args = [\n generateResolvers,\n createNamespaceErrorHandler,\n createOnReadyhandler,\n ]\n if (enableAuth) {\n args.push(\n createAuthMethods\n )\n } else {\n // we just return the obj itself\n args.push(\n (obj) => obj \n )\n }\n\n // run it\n const fn = Reflect.apply(chainFns, null, args)\n return fn(opts, ee, nspSet)\n}\n","// create options\nimport { checkConfigAsync } from 'jsonql-params-validator'\nimport { wsCoreDefaultOptions, wsCoreConstProps } from './defaults'\nimport { fixWss, getHostName } from '../utils'\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 checkOptionsWrapper(config, defaultOptions, constProps) {\n const wsConstProps = Object.assign(wsCoreConstProps, constProps)\n const defaultCheckOptions = Object.assign(wsCoreDefaultOptions, defaultOptions)\n /*\n const fn = postConfigCheck(checkMap, constProps, checkConfig)\n return fn(config)\n */\n return checkConfigAsync(config, defaultCheckOptions, 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 postWsOptions(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 // debug('CONFIGURATION OPTIONS', opts)\n return opts\n })\n}\n\n/**\n * check the configuration\n * @param {object} config user supplied configuration\n * @param {object} defaultOptions the check map\n * @param {object} constProps developer supplied configuration\n * @return {object} after checked\n */\nfunction checkWsCoreOptions(config, defaultOptions, constProps) {\n return checkOptionsWrapper(config, defaultOptions, constProps)\n .then(postWsOptions)\n}\n\nexport {\n wsCoreDefaultOptions,\n wsCoreConstProps,\n checkWsCoreOptions,\n postWsOptions\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 { checkWsCoreOptions } from './options'\nimport { getEventEmitter, processContract, getLogFn } from './utils'\n\n/**\n * 0.5.0 we break up the wsClientCore in two parts one without the config check \n * @param {function} socketClientResolver \n * @param {object} config the already checked config \n */\nexport function wsClientCoreAction(socketClientResolver, config) {\n return Promise\n .resolve(config)\n .then(getLogFn)\n .then(opts => ({\n opts,\n nspMap: processContract(opts),\n ee: getEventEmitter(opts)\n }))\n .then(\n ({opts, nspMap, ee}) => socketClientResolver(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} socketClientResolver this is the one method export by various clients\n * @param {object} [defaultOptions={}] 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(socketClientResolver, defaultOptions = {}, constProps = {}) {\n // we need to inject property to this client later\n // therefore we need to do it this way\n return (config = {}) => (\n checkWsCoreOptions(config, defaultOptions, constProps)\n .then(opts => wsClientCoreAction(socketClientResolver, opts))\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\nconst wsClientAppProps = {}\n\nexport { wsClientAppProps, wsClientConstProps }\n","// pass the different type of ws to generate the client\nimport { TOKEN_PARAM_NAME } from 'jsonql-constants'\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 */\nconst 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 * The bug was in the wsOptions where ws doesn'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 */\nexport function createWsClient(WebSocket, auth = false) {\n if (auth === false) {\n return function createWsClientHandler(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 createWsAuthClientHandler(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","/**\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 * 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 * @return {*} json object on success\n */\nconst parse = function(n) {\n try {\n return JSON.parse(n)\n } catch(e) {\n return n;\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 console.info('obj', obj)\n console.error(e)\n throw new Error(e)\n */\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 parse(n)\n }\n return JSON.parse(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","// 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')) {\n return contract.socket;\n }\n return false;\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 * @param {boolean} [fallback=false] this is a fall back option for old code\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, fallback = false) {\n let socket = extractSocketPart(contract)\n if (socket === false) {\n if (fallback) {\n return contract; // just return the whole contract\n }\n throw new JsonqlError(`socket not found in contract!`)\n }\n let nspSet = {};\n let size = 0;\n let publicNamespace;\n for (let resolverName in socket) {\n let params = socket[resolverName];\n let { namespace } = params;\n if (namespace) {\n if (!nspSet[namespace]) {\n ++size;\n nspSet[namespace] = {};\n }\n nspSet[namespace][resolverName] = params;\n if (!publicNamespace) {\n if (params.public) {\n publicNamespace = namespace;\n }\n }\n }\n }\n return { size, nspSet, publicNamespace }\n}\n\n/**\n * @NOTE ported from jsonql-ws-client\n * Got to make sure the connection order otherwise\n * it will hang\n * @param {object} nspSet contract\n * @param {string} publicNamespace like the name said\n * @return {array} namespaces in order\n */\nexport function getNamespaceInOrder(nspSet, publicNamespace) {\n let names = []; // need to make sure the order!\n for (let namespace in nspSet) {\n if (namespace === publicNamespace) {\n names[1] = namespace;\n } else {\n names[0] = namespace;\n }\n }\n return names;\n}\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'\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\n\nimport isArray from 'lodash-es/isArray'\nimport isPlainObject from 'lodash-es/isPlainObject'\nimport isString from 'lodash-es/isString'\n\nimport { timestamp } from './timestamp'\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) ? JSON.parse(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 * Get name from the payload (ported back from jsonql-koa)\n * @param {*} payload to extract from\n * @return {string} name\n */\nexport function getNameFromPayload(payload) {\n return Object.keys(payload)[0]\n}\n\n/**\n * 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]: payload[TIMESTAMP_PARAM_NAME]\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 = getNameFromPayload(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]: payload[TIMESTAMP_PARAM_NAME]\n }\n }\n }\n return false;\n}\n\n/**\n * @param {object} payload\n * @return {object} resolverName, payload, conditon\n */\nexport function getMutationFromPayload(payload) {\n const result = processPayload(payload, getMutationFromArgs)\n\n if (result !== false) {\n return result;\n }\n throw new JsonqlValidationError('[getMutationArgs] Payload is malformed!', payload)\n}\n","// constants\n\nimport {\n EMIT_REPLY_TYPE,\n JS_WS_SOCKET_IO_NAME,\n JS_WS_NAME,\n ON_MESSAGE_PROP_NAME,\n ON_RESULT_PROP_NAME\n} from 'jsonql-constants'\n\nconst SOCKET_IO = JS_WS_SOCKET_IO_NAME;\nconst WS = JS_WS_NAME;\n\nconst AVAILABLE_SERVERS = [SOCKET_IO, WS]\n\nconst SOCKET_NOT_DEFINE_ERR = 'socket is not define in the contract file!';\n\nconst SERVER_NOT_SUPPORT_ERR = 'is not supported server name!';\n\nconst MISSING_PROP_ERR = 'Missing property in contract!';\n\nconst UNKNOWN_CLIENT_ERR = 'Unknown client type!';\n\nconst EMIT_EVT = EMIT_REPLY_TYPE;\n\nconst NAMESPACE_KEY = 'namespaceMap';\n\nconst UNKNOWN_RESULT = 'UKNNOWN RESULT!';\n\nconst NOT_ALLOW_OP = 'This operation is not allow!';\n\nconst MY_NAMESPACE = 'myNamespace'\n\nconst CB_FN_NAME = 'on'\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_PROP_NAME,\n ON_RESULT_PROP_NAME,\n NAMESPACE_KEY,\n UNKNOWN_RESULT,\n NOT_ALLOW_OP,\n MY_NAMESPACE,\n CB_FN_NAME\n}\n","// since both the ws and io version are\n// pre-defined in the client-generator\n// and this one will have the same parameters\n// and the callback is identical\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 } = opts;\n const url = namespace ? [hostname, namespace].join('/') : wssPath;\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 } = opts;\n const url = namespace ? [hostname, namespace].join('/') : wssPath;\n if (token && typeof token !== 'string') {\n throw new Error(`Expect token to be string, but got ${token}`)\n }\n return nspAuthClient(url, token, wsOptions)\n}\n\nexport {\n createNspClient,\n createNspAuthClient\n}\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","// export\nimport {\n checkIsObject,\n notEmpty,\n checkIsAny,\n checkIsString,\n checkIsBoolean,\n checkIsNumber,\n checkIsArray\n} from './src'\n// PIA syntax\nexport const isObject = checkIsObject;\nexport const isAny = checkIsAny;\nexport const isString = checkIsString;\nexport const isBoolean = checkIsBoolean;\nexport const isNumber = checkIsNumber;\nexport const isArray = checkIsArray;\nexport const isNotEmpty = notEmpty;\n\nimport * as validator from './src/validator'\n\nexport const normalizeArgs = validator.normalizeArgs;\nexport const validateSync = validator.validateSync;\nexport const validateAsync = validator.validateAsync;\n\n// configuration checking\n\nimport * as jsonqlOptions from './src/options'\n\nexport const JSONQL_PARAMS_VALIDATOR_INFO = jsonqlOptions.JSONQL_PARAMS_VALIDATOR_INFO;\n\nexport const createConfig = jsonqlOptions.createConfig;\nexport const constructConfig = jsonqlOptions.constructConfigFn;\n// construct the final output 1.5.2\nexport const checkConfigAsync = jsonqlOptions.getCheckConfigAsync(validator.validateSync)\nexport const checkConfig = jsonqlOptions.getCheckConfig(validator.validateSync)\n\n// export the two extra functions\nimport isInArray from './src/is-in-array'\nimport isObjectHasKeyFn from './src/options/is-key-in-object'\n\nexport const inArray = isInArray;\nexport const isObjectHasKey = isObjectHasKeyFn;\n","// making all the functionality on it's own\n// import { WatchClass } from './watch'\n\nexport default class SuspendClass {\n\n constructor() {\n // suspend, release and queue\n this.__suspend__ = null;\n this.queueStore = new Set()\n /*\n this.watch('suspend', function(value, prop, oldValue) {\n this.logger(`${prop} set from ${oldValue} to ${value}`)\n // it means it set the suspend = true then release it\n if (oldValue === true && value === false) {\n // we want this happen after the return happens\n setTimeout(() => {\n this.release()\n }, 1)\n }\n return value; // we need to return the value to store it\n })\n */\n }\n\n /**\n * setter to set the suspend and check if it's boolean value\n * @param {boolean} value to trigger\n */\n set $suspend(value) {\n if (typeof value === 'boolean') {\n const lastValue = this.__suspend__;\n this.__suspend__ = value;\n this.logger('($suspend)', `Change from ${lastValue} --> ${value}`)\n if (lastValue === true && value === false) {\n setTimeout(() => {\n this.release()\n }, 1)\n }\n } else {\n throw new Error(`$suspend only accept Boolean value!`)\n }\n }\n\n /**\n * queuing call up when it's in suspend mode\n * @param {any} value\n * @return {Boolean} true when added or false when it's not\n */\n $queue(...args) {\n if (this.__suspend__ === true) {\n this.logger('($queue)', 'added to $queue', args)\n // there shouldn't be any duplicate ...\n this.queueStore.add(args)\n }\n return this.__suspend__;\n }\n\n /**\n * a getter to get all the store queue\n * @return {array} Set turn into Array before return\n */\n get $queues() {\n let size = this.queueStore.size;\n this.logger('($queues)', `size: ${size}`)\n if (size > 0) {\n return Array.from(this.queueStore)\n }\n return []\n }\n\n /**\n * Release the queue\n * @return {int} size if any\n */\n release() {\n let size = this.queueStore.size\n this.logger('(release)', `Release was called ${size}`)\n if (size > 0) {\n const queue = Array.from(this.queueStore)\n this.queueStore.clear()\n this.logger('queue', queue)\n queue.forEach(args => {\n this.logger(args)\n Reflect.apply(this.$trigger, this, args)\n })\n this.logger(`Release size ${this.queueStore.size}`)\n }\n }\n}\n","// group all the small functions here\nimport { JS_WS_SOCKET_IO_NAME, JS_WS_NAME, EMIT_REPLY_TYPE } from 'jsonql-constants'\nimport { toArray, createEvt } from 'jsonql-utils/src/generic'\nimport JsonqlValidationError from 'jsonql-errors/src/validation-error'\n// we shouldn't do this anymore\nexport const fixWss = (url, serverType) => {\n // ws only allow ws:// path\n if (serverType === JS_WS_NAME) {\n return url.replace('http://', 'ws://')\n }\n return url\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 * @param {object} nsps namespace as key\n * @param {string} type of server\n */\nexport const disconnect = (nsps, type = JS_WS_SOCKET_IO_NAME) => {\n try {\n // @TODO need to figure out a better way here?\n const method = type === JS_WS_SOCKET_IO_NAME ? 'disconnect' : 'terminate';\n for (let namespace in nsps) {\n let nsp = nsps[namespace]\n if (nsp && nsp[method]) {\n Reflect.apply(nsp[method], null, [])\n }\n }\n } catch(e) {\n // socket.io throw a this.destroy of undefined?\n console.error('Disconnect call failed', e)\n }\n}\n","// this use by client-event-handler\nimport { ON_ERROR_PROP_NAME, ERROR_PROP_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 * @param {object} opts configuration\n * @return {void}\n */\nexport function triggerNamespacesOnError(ee, namespaces, message, opts = {}) {\n const { useCallbackStyle } = opts;\n const ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME;\n namespaces.forEach( namespace => {\n ee.$call(createEvt(namespace, ERROR_SUBFIX), [{ message, namespace }])\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\nimport {\n ERROR_PROP_NAME,\n RESULT_PROP_NAME,\n // LOGIN_EVENT_NAME,\n LOGOUT_EVENT_NAME,\n NOT_LOGIN_ERR_MSG,\n ON_ERROR_PROP_NAME,\n ON_RESULT_PROP_NAME,\n // ON_MESSAGE_PROP_NAME,\n} from 'jsonql-constants'\nimport { EMIT_EVT, SOCKET_IO, WS } from '../options/constants'\nimport { createEvt, clearMainEmitEvt } from '../utils'\nimport { triggerNamespacesOnError } from './trigger-namespaces-on-error'\n\n/**\n * A fake ee handler\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 { useCallbackStyle, log } = opts;\n const ERROR_SUBFIX = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME;\n const RESULT_SUBFIX = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME;\n ee.$only(\n createEvt(namespace, EMIT_EVT),\n function notLoginHandlerCallback(resolverName, args) {\n\n log('[notLoginHandler] hijack the ws call', namespace, resolverName, args)\n\n let error = {\n message: NOT_LOGIN_ERR_MSG\n }\n // It should just throw error here and should not call the result\n // because that's channel for handling normal event not the fake one\n ee.$call(createEvt(namespace, resolverName, ERROR_SUBFIX), [error])\n // also trigger the result handler, but wrap inside the error key\n ee.$call(createEvt(namespace, resolverName, RESULT_SUBFIX), [{ 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 * centralize all the comm in one place\n * @param {object} opts configuration\n * @param {array} namespaces namespace(s)\n * @param {object} ee Event Emitter instance\n * @param {function} bindWsHandler binding the ee to ws --> this is the core bit\n * @param {array} namespaces array of namespace available\n * @param {object} nsps namespaced nsp\n * @return {void} nothing\n */\nexport function clientEventHandler(opts, nspMap, ee, bindWsHandler, namespaces, nsps) {\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 const { log } = opts;\n // loop\n // @BUG for io this has to be in order the one with auth need to get call first\n // The order of login is very import we need to run a waterfall here to make sure\n // one is execute then the other\n namespaces.forEach(namespace => {\n isPrivate = privateNamespace === namespace;\n if (nsps[namespace]) {\n log('[call bindWsHandler]', isPrivate, namespace)\n let args = [namespace, nsps[namespace], ee, isPrivate, opts]\n if (opts.serverType === SOCKET_IO) {\n let { nspSet } = nspMap;\n args.push(nspSet[namespace])\n }\n Reflect.apply(bindWsHandler, null, args)\n } else {\n // a dummy placeholder\n notLoginWsHandler(namespace, ee, opts)\n }\n })\n // this will be available regardless enableAuth\n // because the server can log the client out\n ee.$on(LOGOUT_EVENT_NAME, function logoutEvtHandler() {\n log('LOGOUT_EVENT_NAME')\n // disconnect(nsps, opts.serverType)\n // we need to issue error to all the namespace onError handler\n triggerNamespacesOnError(ee, namespaces, LOGOUT_EVENT_NAME)\n // rebind all of the handler to the fake one\n namespaces.forEach( namespace => {\n clearMainEmitEvt(ee, namespace)\n // clear out the nsp\n nsps[namespace] = false;\n // add a NOT LOGIN error if call\n notLoginWsHandler(namespace, ee, opts)\n })\n })\n}\n","// take the ws reply data for use\nimport { WS_EVT_NAME, WS_DATA_NAME, WS_REPLY_TYPE } from 'jsonql-constants'\nimport { isString } from 'jsonql-params-validator'\nimport { isObjectHasKey } from 'jsonql-utils/module'\nimport { JsonqlError, clientErrorsHandler } from 'jsonql-errors'\n\nconst keys = [ WS_REPLY_TYPE, WS_EVT_NAME, WS_DATA_NAME ]\n\n/**\n * @param {object} payload should be string when reply but could be transformed\n * @return {boolean} true is OK\n */\nconst isWsReply = payload => {\n const { data } = payload\n if (data) {\n let result = keys.filter(key => isObjectHasKey(data, key))\n return (result.length === keys.length) ? data : false\n }\n return false\n}\n\n/**\n * @param {object} payload This is the entire ws Event Object\n * @return {object} false on failed\n */\nconst extractWsPayload = payload => {\n const { data } = payload;\n let json = isString(data) ? JSON.parse(data) : data\n let fdata;\n if ((fdata = isWsReply(json)) !== false) {\n return {\n resolverName: fdata[WS_EVT_NAME],\n data: fdata[WS_DATA_NAME],\n type: fdata[WS_REPLY_TYPE]\n }\n }\n throw new JsonqlError('payload can not be decoded', payload)\n}\n// export it\nexport default extractWsPayload\n","// the WebSocket main handler\nimport {\n LOGIN_EVENT_NAME,\n LOGOUT_EVENT_NAME,\n ACKNOWLEDGE_REPLY_TYPE,\n EMIT_REPLY_TYPE,\n ERROR_TYPE,\n\n ON_ERROR_PROP_NAME,\n ON_MESSAGE_PROP_NAME,\n ON_RESULT_PROP_NAME,\n ON_READY_PROP_NAME,\n ON_LOGIN_PROP_NAME,\n\n ERROR_PROP_NAME,\n MESSAGE_PROP_NAME,\n RESULT_PROP_NAME,\n READY_PROP_NAME,\n LOGIN_PROP_NAME\n} from 'jsonql-constants'\nimport { createQueryStr, createEvt } from 'jsonql-utils/module'\nimport extractWsPayload from './extract-ws-payload'\n\n\n/**\n * under extremely circumstances we might not even have a resolverName, then\n * we issue a global error for the developer to catch it\n * @param {object} ee event emitter\n * @param {string} namespace nsp\n * @param {string} resolverName resolver\n * @param {object} json decoded payload or error object\n * @param {string} ERROR_EVT_NAME the error event name\n * @return {undefined} nothing return\n */\nconst errorTypeHandler = (ee, namespace, resolverName, json, ERROR_EVT_NAME) => {\n let evt = [namespace]\n if (resolverName) {\n evt.push(resolverName)\n }\n evt.push(ERROR_EVT_NAME)\n let evtName = Reflect.apply(createEvt, null, evt)\n // test if there is a data field\n let payload = json.data || json;\n ee.$trigger(evtName, [payload])\n}\n\n/**\n * Binding the even to socket normally\n * @param {string} namespace\n * @param {object} ws the nsp\n * @param {object} ee EventEmitter\n * @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 wsMainHandler(namespace, ws, ee, isPrivate, opts) {\n const { useCallbackStyle, log } = opts;\n\n log(`wsMainHandler log test`)\n\n const READY_EVT_NAME = useCallbackStyle ? READY_PROP_NAME : ON_READY_PROP_NAME;\n const LOGIN_EVT_NAME = useCallbackStyle ? LOGIN_PROP_NAME : ON_LOGIN_PROP_NAME;\n const MESSAGE_EVT_NAME = useCallbackStyle ? MESSAGE_PROP_NAME : ON_MESSAGE_PROP_NAME;\n const RESULT_EVT_NAME = useCallbackStyle ? RESULT_PROP_NAME : ON_RESULT_PROP_NAME;\n const ERROR_EVT_NAME = useCallbackStyle ? ERROR_PROP_NAME : ON_ERROR_PROP_NAME;\n // connection open\n ws.onopen = function onOpenCallback() {\n log('ws.onopen listened')\n // we just call the onReady\n ee.$call(READY_EVT_NAME, namespace)\n // need an extra parameter here to id the private nsp\n if (isPrivate) {\n log(`isPrivate and fire the ${LOGIN_EVT_NAME}`)\n ee.$call(LOGIN_EVT_NAME, namespace)\n }\n // add listener only after the open is called\n ee.$only(\n createEvt(namespace, EMIT_REPLY_TYPE),\n function wsMainOnEvtHandler(resolverName, args) {\n log('calling server', resolverName, args)\n ws.send(\n createQueryStr(resolverName, args)\n )\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 const json = extractWsPayload(payload)\n const { resolverName, type } = json;\n log('Hear from server', type, json)\n switch (type) {\n case EMIT_REPLY_TYPE:\n let e1 = createEvt(namespace, resolverName, MESSAGE_EVT_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, RESULT_EVT_NAME)\n let x = ee.$trigger(e2, [json])\n // log(`ACKNOWLEDGE_REPLY_TYPE`, e2, json)\n break;\n case ERROR_TYPE:\n // this is handled error and we won't throw it\n // we need to extract the error from json\n log(`ERROR_TYPE`)\n errorTypeHandler(ee, namespace, resolverName, json, ERROR_EVT_NAME)\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, ERROR_EVT_NAME)\n // let error = {error: {'message': 'Unhandled event!', type}};\n // ee.$trigger(createEvt(namespace, resolverName, ON_RESULT_PROP_NAME), [error])\n }\n } catch(e) {\n console.error(`ws.onmessage error`, e)\n errorTypeHandler(ee, namespace, false, e, ERROR_EVT_NAME)\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 // listen to the LOGOUT_EVENT_NAME\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","// actually binding the event client to the socket client\nimport { getNameFromPayload, getNamespaceInOrder } from 'jsonql-utils/module'\nimport { LOGIN_EVENT_NAME, LOGOUT_EVENT_NAME, JS_WS_NAME } from 'jsonql-constants'\nimport {\n createNspClient,\n createNspAuthClient,\n clientEventHandler,\n // comment them out for now they are not in use\n // triggerNamespacesOnError,\n // disconnect\n clearMainEmitEvt\n} from 'jsonql-ws-client-core/share'\nimport { wsMainHandler } from './ws-main-handler'\n\n/**\n * Because the nsps can be throw away so it doesn't matter the scope\n * this will get reuse again\n * @param {object} opts configuration\n * @param {object} nspMap from contract\n * @param {string|null} token whether we have the token at run time\n * @return {object} nsps namespace with namespace as key\n */\nconst createNsps = function(opts, nspMap, token) {\n let { nspSet, publicNamespace } = nspMap\n let login = false\n let namespaces = []\n let nsps = {}\n // first we need to binding all the events handler\n if (opts.enableAuth) { // && opts.useJwt\n login = true; // just saying we need to listen to login event\n namespaces = getNamespaceInOrder(nspSet, publicNamespace)\n nsps = namespaces.map((namespace, i) => {\n if (i === 0) {\n if (token) {\n opts.token = token\n // console.log('create createNspAuthClient at run time', opts)\n return {[namespace]: createNspAuthClient(namespace, opts)}\n }\n return {[namespace]: false}\n }\n return {[namespace]: createNspClient(namespace, opts)}\n }).reduce((first, next) => Object.assign(first, next), {})\n } else {\n let namespace = getNameFromPayload(nspSet)\n namespaces.push(namespace)\n // standard without login\n // the stock version should not have a namespace\n nsps[namespace] = createNspClient(false, opts)\n }\n // return\n return { nsps, namespaces, login }\n}\n\n/**\n * create a ws client\n * @param {object} opts configuration\n * @param {object} nspMap namespace with resolvers\n * @param {object} ee EventEmitter to pass through\n * @return {object} what comes in what goes out\n */\nexport function createClient(opts, nspMap, ee) {\n // arguments that don't change\n const args = [opts, nspMap, ee, wsMainHandler]\n // now create the nsps\n const { token, log } = opts\n const { nsps, namespaces, login } = createNsps(opts, nspMap, token)\n // binding the listeners - and it will listen to LOGOUT event\n // to unbind itself, and the above call will bind it again\n Reflect.apply(clientEventHandler, null, args.concat([namespaces, nsps]))\n // setup listener\n if (login) {\n ee.$only(LOGIN_EVENT_NAME, function loginEventHandler(tokenLater) {\n\n log('createClient LOGIN_EVENT_NAME')\n\n // debugFn(`LOGIN_EVENT_NAME called with token:`, tokenLater)\n // @BUG 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\n // disconnect(nsps, JS_WS_NAME)\n\n // @TODO should we trigger error on this one?\n // triggerNamespacesOnError(ee, namespaces, LOGIN_EVENT_NAME)\n clearMainEmitEvt(ee, namespaces)\n // console.log('LOGIN_EVENT_NAME', token)\n const newNsps = createNsps(opts, nspMap, tokenLater)\n // rebind it\n Reflect.apply(\n clientEventHandler,\n null,\n args.concat([newNsps.namespaces, newNsps.nsps])\n )\n })\n }\n // return what input\n return { opts, nspMap, ee }\n}\n","// share method to create the wsClientResolver\n\nimport { createWsClient } from './create-ws-client'\nimport { createClient } from './create-client'\n\n/**\n * combine the create client resolver\n * @param {object} ws the different WebSocket module\n * @return {function} the wsClientResolver\n */\nexport default function createClientResolver(ws) {\n const client = createWsClient(ws)\n const authClient = createWsClient(ws, true)\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(opts, nspMap, ee) {\n opts.nspClient = client;\n opts.nspAuthClient = authClient;\n // @1.0.7 remove later once everything fixed \n const { log } = opts;\n if (log && typeof log === 'function') {\n log('@jsonql/ws ee', ee.name)\n log('@jsonql/ws createClientResolver', opts)\n }\n // console.log(`contract`, opts.contract)\n return createClient(opts, nspMap, ee)\n }\n}\n","// 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 createClientResolver from './core/create-client-resolver'\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 createClientResolver(WebSocket)\n","// this is the module entry point for node\nimport { wsClientCore } from '../../../ws-client-core' //'jsonql-ws-client-core'\nimport { wsClientAppProps, wsClientConstProps } from './options'\nimport wsClientResolver from './node-ws-client-resolver'\n\n// export back the function and that's it\nexport default function wsBrowserClient(config = {}, constProps = {}) {\n const initMethod = wsClientCore(wsClientResolver, wsClientAppProps, Object.assign(wsClientConstProps, constProps))\n return initMethod(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;;;;;;;;;;;;;"} \ No newline at end of file diff --git a/packages/@jsonql/ws/src/node.js b/packages/@jsonql/ws/src/node.js index 7f6994d8..d0815af5 100644 --- a/packages/@jsonql/ws/src/node.js +++ b/packages/@jsonql/ws/src/node.js @@ -1,5 +1,5 @@ // this is the module entry point for node -import { wsClientCore } from 'jsonql-ws-client-core' +import { wsClientCore } from '../../../ws-client-core' //'jsonql-ws-client-core' import { wsClientAppProps, wsClientConstProps } from './options' import wsClientResolver from './node-ws-client-resolver' diff --git a/packages/@jsonql/ws/node-org.js b/packages/@jsonql/ws/tests/previous/node.js similarity index 100% rename from packages/@jsonql/ws/node-org.js rename to packages/@jsonql/ws/tests/previous/node.js diff --git a/packages/@jsonql/ws/node-org.js.map b/packages/@jsonql/ws/tests/previous/node.js.map similarity index 100% rename from packages/@jsonql/ws/node-org.js.map rename to packages/@jsonql/ws/tests/previous/node.js.map diff --git a/packages/@jsonql/ws/tests/ws-client-basic.test.js b/packages/@jsonql/ws/tests/ws-client-basic.test.js index a3eae5da..1c8e220e 100644 --- a/packages/@jsonql/ws/tests/ws-client-basic.test.js +++ b/packages/@jsonql/ws/tests/ws-client-basic.test.js @@ -2,7 +2,7 @@ const test = require('ava') const { join } = require('path') const fsx = require('fs-extra') -const { JS_WS_NAME } = require('jsonql-constants') +// const { JS_WS_NAME } = require('jsonql-constants') const wsClient = require('../main') const serverSetup = require('./fixtures/server-setup') @@ -45,10 +45,11 @@ test.cb('It should able to connect to the ws server', t => { t.plan(2) let client = t.context.client - let ver = client.devHelpers.getVer() - t.truthy(ver) - client.simple(100) + .then(result => { + t.is(101, result) + }) + client.simple.onResult = (result) => { t.is(101, result) t.end() @@ -57,7 +58,7 @@ test.cb('It should able to connect to the ws server', t => { test.cb('It should able to handle error', t => { t.plan(1) - let client = t.context.client; + let client = t.context.client client.throwError() @@ -71,7 +72,10 @@ test.cb('It should able to handle error', t => { test.cb('It should able to send message back while its talking to the server', t => { t.plan(1) let c = 0; - let client = t.context.client; + let client = t.context.client + + debug(client) + client.continuous('Jumping') client.continuous.onResult = (msg) => { ++c; -- Gitee From e52b2524a0d2d378feb18f95055d72efed5a97ce Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 4 Mar 2020 09:01:00 +0800 Subject: [PATCH 25/26] update the ws-server-core --- packages/ws-server-core/README.md | 6 +++++ packages/ws-server-core/package.json | 2 +- .../src/{share => options}/constants.js | 0 .../ws-server-core/src/share/add-property.js | 2 +- packages/ws-server-core/src/share/helpers.js | 6 ++--- packages/ws-server/package.json | 2 +- packages/ws-server/src/core/verify-client.js | 2 ++ packages/ws-server/src/core/ws-setup.js | 11 +++++---- .../ws-server/tests/ws-connect-error.test.js | 2 +- .../ws-server/tests/ws-connect-es6.test.js | 23 +++++++++---------- packages/ws-server/tests/ws-connect.test.js | 12 +++++----- packages/ws-server/tests/ws-jwt-auth.test.js | 7 +++--- 12 files changed, 41 insertions(+), 34 deletions(-) rename packages/ws-server-core/src/{share => options}/constants.js (100%) diff --git a/packages/ws-server-core/README.md b/packages/ws-server-core/README.md index e3f4397a..6e24c6f6 100644 --- a/packages/ws-server-core/README.md +++ b/packages/ws-server-core/README.md @@ -25,6 +25,12 @@ This is for our own reference use **ONLY**: - jsonqlWsServerCore - jsonqlWsServerCoreAction +## Note to ourself + +The main functionality of this module is: + +- + --- [NEWBRAN LTD UK](https://newbran.ch) diff --git a/packages/ws-server-core/package.json b/packages/ws-server-core/package.json index ee0c0bab..cd04cd76 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.4.0", + "version": "0.4.1", "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/share/constants.js b/packages/ws-server-core/src/options/constants.js similarity index 100% rename from packages/ws-server-core/src/share/constants.js rename to packages/ws-server-core/src/options/constants.js diff --git a/packages/ws-server-core/src/share/add-property.js b/packages/ws-server-core/src/share/add-property.js index 7ea4f9c2..10394399 100644 --- a/packages/ws-server-core/src/share/add-property.js +++ b/packages/ws-server-core/src/share/add-property.js @@ -52,7 +52,7 @@ const addProperty = (fn, resolverName, ws, userdata, opts) => { .then(clients => injectNodeClient(resolver, clients)) } // @TODO what if we run this standalone and we want to inject clients to it? - return resolver; + return resolver }) } diff --git a/packages/ws-server-core/src/share/helpers.js b/packages/ws-server-core/src/share/helpers.js index ab8d6a53..a1ccc80b 100644 --- a/packages/ws-server-core/src/share/helpers.js +++ b/packages/ws-server-core/src/share/helpers.js @@ -10,7 +10,7 @@ const { isString } = require('jsonql-params-validator') const { JsonqlError, clientErrorsHandler } = require('jsonql-errors') const { toJson, isObjectHasKey } = require('jsonql-utils') -const { MODULE_NAME } = require('./constants') +const { MODULE_NAME } = require('../options/constants') // create debug const debug = require('debug') // const _debug = getDebug('helpers') @@ -68,7 +68,7 @@ const extractWsPayload = payload => { // this was never handled? clientErrorsHandler(json) // now handle the data - let _data; + let _data if ((_data = isWsReply(json)) !== false) { return { data: toJson(_data[WS_DATA_NAME]), @@ -88,7 +88,7 @@ const extractWsPayload = payload => { * @return {array} of namespace(s) */ const getNamespace = function(config) { - const base = JSONQL_PATH; + const base = JSONQL_PATH if (config.enableAuth) { // the public come first return [ diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json index 996a0234..9767390e 100755 --- a/packages/ws-server/package.json +++ b/packages/ws-server/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-ws-server", - "version": "1.6.0", + "version": "1.6.1", "description": "Setup WebSocket server for the jsonql to run on the same host, automatic generate public / private channel using contract", "main": "index.js", "files": [ diff --git a/packages/ws-server/src/core/verify-client.js b/packages/ws-server/src/core/verify-client.js index db4b21f2..86e725a1 100644 --- a/packages/ws-server/src/core/verify-client.js +++ b/packages/ws-server/src/core/verify-client.js @@ -1,4 +1,6 @@ +// @TBC each different server might have different way to verify the client? // export the verifyClient at init time for a handshake authentication + const url = require('url') const { TOKEN_PARAM_NAME } = require('jsonql-constants') const { jwtDecode } = require('jsonql-jwt') diff --git a/packages/ws-server/src/core/ws-setup.js b/packages/ws-server/src/core/ws-setup.js index 14608a1e..c4bd3d34 100644 --- a/packages/ws-server/src/core/ws-setup.js +++ b/packages/ws-server/src/core/ws-setup.js @@ -9,7 +9,6 @@ const { LOGOUT_NAME, TIMESTAMP_PARAM_NAME } = require('jsonql-constants') -const WS_EXIT_ID = 1; const { getDebug, createWsReply, @@ -17,6 +16,7 @@ const { resolveMethod } = require('jsonql-ws-server-core') +const WS_EXIT_ID = 1 const debug = getDebug('ws-setup') /** @@ -39,7 +39,7 @@ const fnHandler = (ws, payload, resolverName, params, opts, userdata) => { return validateAsync(payload.args, params.params, true) .then(args => resolveMethod( resolverName, - args, // this is the clear value from validateAsync + args, // this is the clean value from validateAsync params, opts, ws, @@ -69,7 +69,8 @@ const fnHandler = (ws, payload, resolverName, params, opts, userdata) => { * @return {void} nothing */ const callNspHandler = (ws, json, socketFns, opts, userdata = false) => { - const ts = json[TIMESTAMP_PARAM_NAME] // keep this for use later + debug('TIMESTAMP_PARAM_NAME', json[TIMESTAMP_PARAM_NAME], TIMESTAMP_PARAM_NAME) + // const ts = json[TIMESTAMP_PARAM_NAME] // keep this for use later for (let resolverName in json) { if (resolverName !== TIMESTAMP_PARAM_NAME) { // dirty hack for now // dirty hack @@ -98,11 +99,11 @@ const handleLogout = ws => { */ const wsSetup = (opts, nspObj) => { let nspInfo = {}; - const socketFns = opts.contract.socket; + const socketFns = opts.contract.socket if (opts.enableAuth) { nspInfo = groupByNamespace(socketFns, true) } - let { publicNamespace, nspSet } = nspInfo; + let { publicNamespace, nspSet } = nspInfo for (let namespace in nspObj) { let userdata; nspObj[namespace].on('connection', (ws, req) => { diff --git a/packages/ws-server/tests/ws-connect-error.test.js b/packages/ws-server/tests/ws-connect-error.test.js index 132ac6cb..a5350dc7 100644 --- a/packages/ws-server/tests/ws-connect-error.test.js +++ b/packages/ws-server/tests/ws-connect-error.test.js @@ -39,7 +39,7 @@ test.after(t => { test.cb(`It should able to extract the error object when error throw from the server side`, t => { t.plan(4) // connect to the server - let client = t.context.client; + let client = t.context.client client.on('open', () => { client.send( createPayload('causeError', msg + ' 3nd') ) diff --git a/packages/ws-server/tests/ws-connect-es6.test.js b/packages/ws-server/tests/ws-connect-es6.test.js index 3d3de7d7..fa4f1224 100644 --- a/packages/ws-server/tests/ws-connect-es6.test.js +++ b/packages/ws-server/tests/ws-connect-es6.test.js @@ -17,9 +17,9 @@ const contract = fsx.readJsonSync(contractFile) const { extractWsPayload } = require('jsonql-ws-server-core') const createPayload = require('./fixtures/create-payload') -const port = 8897; -const msg = 'Something'; -let ctn = 0; +const port = 8897 +const msg = 'Something' + test.before(async t => { const { app, io } = await wsServer({ @@ -32,17 +32,16 @@ test.before(async t => { t.context.server.listen(port) t.context.client = wsNodeClient(`ws://localhost:${port}/${JSONQL_PATH}`) -}); +}) test.after(t => { t.context.server.close() }) -test.cb('Grouping all test together as one because the way ws reponse to on.message', t => { +test.cb('Grouping all ES6 test together as one because the way ws reponse to on.message', t => { t.plan(9) // connect to the server - let client = t.context.client; - + let client = t.context.client client.on('open', () => { @@ -55,7 +54,7 @@ test.cb('Grouping all test together as one because the way ws reponse to on.mess }, 500) }) - let i = 0; + let i = 0 const shouldEnd = (ctn, t) => { if (ctn > 2) { @@ -76,18 +75,18 @@ test.cb('Grouping all test together as one because the way ws reponse to on.mess // (2) t.truthy(json.data, 'wsHandler should reply with a message') shouldEnd(++i, t) - break; + break case 'chatroom': // (3) t.truthy(json.data, 'chatroom should reply with a message') shouldEnd(++i, t) - break; + break default: debug('catch error here %O', json) - let { data } = json; + let { data } = json t.truthy(data.error, 'causeError should have error field') - t.is(json.type, ERROR_TYPE) + t.is(json.type, ERROR_TYPE, 'with a ERROR_TYPE field') t.is(data.error.className, 'JsonqlResolverAppError', 'Expect to received resolver app error') t.is(data.error.message, 'causeError', 'Expect to get the resolver name via message field') diff --git a/packages/ws-server/tests/ws-connect.test.js b/packages/ws-server/tests/ws-connect.test.js index e6b4c1b8..5849ec05 100644 --- a/packages/ws-server/tests/ws-connect.test.js +++ b/packages/ws-server/tests/ws-connect.test.js @@ -36,11 +36,11 @@ test.after(t => { t.context.server.close() }) -test.cb('Grouping all test together as one because the way ws reponse to on.message', t => { +test.cb('Grouping all CJS test together as one because the way WS reponse to on.message', t => { t.plan(3) - let tested = 0; + let tested = 0 // connect to the server - let client = t.context.client; + let client = t.context.client t.is(true , t.context.io[JSONQL_PATH] !== undefined) client.on('open', () => { client.send( createPayload('wsHandler', msg + ' 1st', Date.now()) ) @@ -49,7 +49,7 @@ test.cb('Grouping all test together as one because the way ws reponse to on.mess // wait for reply client.on('message', (data) => { - let json; + let json try { json = extractWsPayload(data) @@ -62,14 +62,14 @@ test.cb('Grouping all test together as one because the way ws reponse to on.mess if (tested > 1) { t.end() } - break; + break case 'chatroom': t.truthy(json.data, 'chatroom should reply with a message') ++tested if (tested > 1) { t.end() } - break; + break default: } } catch(e) { diff --git a/packages/ws-server/tests/ws-jwt-auth.test.js b/packages/ws-server/tests/ws-jwt-auth.test.js index bd9e4c5b..1c9264e5 100644 --- a/packages/ws-server/tests/ws-jwt-auth.test.js +++ b/packages/ws-server/tests/ws-jwt-auth.test.js @@ -38,7 +38,6 @@ test.before(async t => { const baseUrl = `ws://localhost:${port}/${JSONQL_PATH}/`; // @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) }) @@ -50,7 +49,7 @@ test.cb('It should able to connect to public namespace without a token', t => { // connect to the private channel t.plan(2) - let client = t.context.client_public; + let client = t.context.client_public t.truthy(t.context.io[ [JSONQL_PATH, 'public'].join('/') ]) @@ -59,7 +58,7 @@ test.cb('It should able to connect to public namespace without a token', t => { }) client.on('message', data => { - let json = extractWsPayload(data); + let json = extractWsPayload(data) // debug('reply', json) t.truthy(json.data) t.end() @@ -69,7 +68,7 @@ test.cb('It should able to connect to public namespace without a token', t => { test.cb('It should able to connect to the private namespace', t => { t.plan(2) - let client = t.context.client_private; + let client = t.context.client_private t.truthy(t.context.io[[JSONQL_PATH, 'private'].join('/')]) -- Gitee From 2eaf35f48e97ea0bd9eb4751ed8002925273dcb2 Mon Sep 17 00:00:00 2001 From: joelchu Date: Wed, 4 Mar 2020 09:04:38 +0800 Subject: [PATCH 26/26] update README to have a clear idea what ws-server-core does --- packages/ws-server-core/README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/ws-server-core/README.md b/packages/ws-server-core/README.md index 6e24c6f6..43a295a9 100644 --- a/packages/ws-server-core/README.md +++ b/packages/ws-server-core/README.md @@ -6,6 +6,14 @@ This module is not intend to use directly. Check [jsonql.org](http://jsonql.org) for more information. +## Note + +The main functionality of this module is: + +- Setup all the default configuration options +- Setup the resolver handlers, and prepare the resolver to act +- Setting up the NSP(s) public and private to handle authentication (or not) + ## Export modules This is for our own reference use **ONLY**: @@ -25,11 +33,6 @@ This is for our own reference use **ONLY**: - jsonqlWsServerCore - jsonqlWsServerCoreAction -## Note to ourself - -The main functionality of this module is: - -- --- -- Gitee