diff --git a/packages/@jsonql/koa/index.js b/packages/@jsonql/koa/index.js index a8f3e3d7a12d3f5f42071c019a2d98105fefff15..5e0336483fde3cf7dc290918c4761102be13ce6e 100644 --- a/packages/@jsonql/koa/index.js +++ b/packages/@jsonql/koa/index.js @@ -20,16 +20,16 @@ class JsonqlKoaServer { this.app = app; this.ws = ws; this.started = false; - if (this.opts.autoStart) { + if (this.opts.autoStart && this.opts.port) { this.start() } } // start the server - start() { + start(port) { if (!this.started) { - console.info(`Server version: ${version} start on ${this.opts.port}`) - this.server.listen(this.opts.port) + console.info(`Server version: ${version} start on ${port || this.opts.port}`) + this.server.listen(port || this.opts.port) this.started = true; } } diff --git a/packages/@jsonql/koa/package.json b/packages/@jsonql/koa/package.json index 30fcfdf6c6c4c65194e7f441830d8b24a845c306..e32cf583a0676669baac53f6df4951293934794f 100644 --- a/packages/@jsonql/koa/package.json +++ b/packages/@jsonql/koa/package.json @@ -1,8 +1,13 @@ { "name": "@jsonql/koa", - "version": "0.5.0", + "version": "0.5.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": [ + "cli.js", + "index.js", + "src" + ], "scripts": { "test": "ava --verbose", "test:basic": "DEBUG=jsonql-koa* ava --verbose ./tests/basic.test.js", @@ -52,16 +57,17 @@ "dependencies": { "debug": "^4.1.1", "fs-extra": "^8.1.0", - "jsonql-constants": "^1.8.10", - "jsonql-koa": "^1.4.17", + "jsonql-constants": "^1.8.11", + "jsonql-koa": "^1.4.18", "jsonql-params-validator": "^1.4.11", + "jsonql-utils": "^0.8.5", "koa": "^2.11.0", "koa-bodyparser": "^4.2.1", "koa-cors": "0.0.16", "yargs": "^15.0.2" }, "optionalDependencies": { - "jsonql-ws-server": "^1.4.3" + "jsonql-ws-server": "^1.4.4" }, "bin": { "jsonql-koa-cli": "./cli.js" diff --git a/packages/@jsonql/koa/src/init-server.js b/packages/@jsonql/koa/src/init-server.js index 46547543727ca51f52f3ceca8ebf36496772885f..4037edb6f2ca1f1f0117d497dc90bf3663bda6e6 100644 --- a/packages/@jsonql/koa/src/init-server.js +++ b/packages/@jsonql/koa/src/init-server.js @@ -5,6 +5,7 @@ const bodyparser = require('koa-bodyparser') const cors = require('koa-cors') // const { jsonqlKoa } = require('../../../koa/main') const { jsonqlKoa } = require('jsonql-koa') +// const { chainFns } = require('jsonql-utils') const { getSocketServer } = require('./get-socket-server') // const debug = require('debug')('jsonql-koa:init-server') @@ -18,7 +19,7 @@ function initServer(config, middlewares) { const app = new Koa() // apply default middlewares app.use(bodyparser()) - if (config.cors === true) { // default is true + if (config.cors === true) { // default is true app.use(cors()) } // init jsonqlKoa @@ -30,8 +31,6 @@ function initServer(config, middlewares) { const server = http.createServer(app.callback()) - // debug('config for socket server', config) - const ws = getSocketServer(config, server) // return it return { server, app, ws } diff --git a/packages/@jsonql/koa/tests/auth.test.js b/packages/@jsonql/koa/tests/auth.test.js index 27aa6b55c48a98373a5719c1a2c734fc64ab3ee3..1335642128dcbd3dc41cdf4ebc64a67a88672e39 100644 --- a/packages/@jsonql/koa/tests/auth.test.js +++ b/packages/@jsonql/koa/tests/auth.test.js @@ -10,13 +10,13 @@ const contractDir = join(contractBaseDir, AUTH_DIR) const port = 8082; test.before(t => { - const { stop } = jsonqlKoaServer({ + const jsonqlKoaInt = jsonqlKoaServer({ port: port, autoStart: true, enableAuth: true }) - t.context.stop = stop; + t.context.stop = () => jsonqlKoaInt.stop(); }) test.after( t => { diff --git a/packages/@jsonql/koa/tests/basic.test.js b/packages/@jsonql/koa/tests/basic.test.js index 4db99eb0da4a4c549d17e165c86514f16448386e..1113f9a70e25b7d731fcc29f224de93ca6a16b39 100644 --- a/packages/@jsonql/koa/tests/basic.test.js +++ b/packages/@jsonql/koa/tests/basic.test.js @@ -12,12 +12,14 @@ const contractDir = join(contractBaseDir, BASIC_DIR) const jsonqlKoaServer = require('./fixtures/test-server') test.before(t => { - const { stop } = jsonqlKoaServer({ + const jsonqlKoaInt = jsonqlKoaServer({ port: 8001, autoStart: true }) - t.context.stop = stop; + // debug(jsonqlKoaInt) + + t.context.stop = () => jsonqlKoaInt.stop(); }) test.after(t => { diff --git a/packages/@jsonql/koa/tests/ms.test.js b/packages/@jsonql/koa/tests/ms.test.js index 108cefbf317dcaf83e7f333c5023d89d020fcc4b..8e4f0add73f453a500c9d7e49d0e1b123bfd6e46 100644 --- a/packages/@jsonql/koa/tests/ms.test.js +++ b/packages/@jsonql/koa/tests/ms.test.js @@ -15,7 +15,7 @@ const createMsTestServer = require('./fixtures/ms-test-servers') const getClientA = async () => ( await jsonqlNodeClient({ hostname: `http://localhost:${PORT_A}`, - contractDir: join(__dirname, 'fixtures', 'contract', 'client1'), + contractDir: join(contractBaseDir, 'client1'), serverType: 'ws' }) ) @@ -30,6 +30,11 @@ test.after(t => { t.context.serverA.stop() t.context.serverB.stop() + fsx.removeSync(contractDirA) + fsx.removeSync(contractDirB) + + // fsx.removeSync(join(contractBaseDir, 'client1')) + // fsx.removeSync(join(contractBaseDir, 'client2')) }) test(`It should able to connect to service A directly`, async t => { @@ -43,7 +48,7 @@ test(`It should able to connect to service A directly`, async t => { test(`It should able to connect to server B directly`, async t => { const client2 = await jsonqlNodeClient({ hostname: `http://localhost:${PORT_B}`, - contractDir: join(__dirname, 'fixtures', 'contract', 'client2') + contractDir: join(contractBaseDir, 'client2') }) const res2 = await client2.query.helloWorld() t.is(res2, HELLO) @@ -60,7 +65,7 @@ test(`It should able to connect to another service via the internal nodeClient`, t.truthy(msg) }) -test.cb.only(`It should able to connect to the another client via socket connection`, t => { +test.cb(`It should able to connect to the another client via socket connection`, t => { t.plan(2) getClientA() .then(client => { diff --git a/packages/@jsonql/koa/tests/socket.test.js b/packages/@jsonql/koa/tests/socket.test.js index 8ecc71b94f5062755c30e739b85fe789e544dff5..b4f5d6ada3f7aa8cd392115d9ee05bf7276822f1 100644 --- a/packages/@jsonql/koa/tests/socket.test.js +++ b/packages/@jsonql/koa/tests/socket.test.js @@ -11,7 +11,7 @@ const keysDir = join(contractBaseDir, [SOCKET_DIR, 'keys'].join('-')) const port = 8083; test.before(t => { - const { stop, start } = jsonqlKoaServer({ + const jsonqlKoaInt = jsonqlKoaServer({ port, keysDir, contractDir, @@ -19,9 +19,9 @@ test.before(t => { serverType: JS_WS_NAME }) - t.context.stop = stop; + t.context.stop = () => jsonqlKoaInt.stop(); - start() + jsonqlKoaInt.start() }) diff --git a/packages/constants/README.md b/packages/constants/README.md index 2bd7caf9b632c465a628334264345343a9f328d0..5f90c19ee67b44625451a29f2eeadf49754c44eb 100755 --- a/packages/constants/README.md +++ b/packages/constants/README.md @@ -36,6 +36,7 @@ non-javascript to develop your tool. You can also use the included `constants.js - CONDITION_PARAM_NAME - RESOLVER_PARAM_NAME - QUERY_ARG_NAME +- TIMESTAMP_PARAM_NAME - MUTATION_ARGS - JSONP_CALLBACK_NAME - API_REQUEST_METHODS diff --git a/packages/constants/constants.json b/packages/constants/constants.json index 7cc280c35f6684afc548fed7dd93344ccba48e1f..15d4bfba768a29cc15c00ec86f6618e441268c58 100644 --- a/packages/constants/constants.json +++ b/packages/constants/constants.json @@ -32,6 +32,7 @@ "CONDITION_PARAM_NAME": "condition", "RESOLVER_PARAM_NAME": "resolverName", "QUERY_ARG_NAME": "args", + "TIMESTAMP_PARAM_NAME": "TS", "MUTATION_ARGS": [ "resolverName", "payload", diff --git a/packages/constants/main.js b/packages/constants/main.js index 6b493cd51f89c4a8f55b6bb333b2b0dbb56fd0c6..c3ec08fdf4b3d02fde5935fae4e77f087148a4fb 100644 --- a/packages/constants/main.js +++ b/packages/constants/main.js @@ -32,6 +32,7 @@ module.exports = { "CONDITION_PARAM_NAME": "condition", "RESOLVER_PARAM_NAME": "resolverName", "QUERY_ARG_NAME": "args", + "TIMESTAMP_PARAM_NAME": "TS", "MUTATION_ARGS": [ "resolverName", "payload", diff --git a/packages/constants/module.js b/packages/constants/module.js index 3c5213db570a25ca60153909027192524512a708..8f5d2a10f8c870cba9f756e6d316fb6c6685804c 100644 --- a/packages/constants/module.js +++ b/packages/constants/module.js @@ -39,10 +39,11 @@ export const SOCKET_NAME = 'socket'; export const CONTRACT_NAME = 'contract'; export const RESOLVER_TYPES = [QUERY_NAME, MUTATION_NAME, SOCKET_NAME]; // for calling the mutation -export const PAYLOAD_PARAM_NAME = 'payload'; +export const PAYLOAD_PARAM_NAME = 'payload'; // @TODO shortern them export const CONDITION_PARAM_NAME = 'condition'; export const RESOLVER_PARAM_NAME = 'resolverName'; export const QUERY_ARG_NAME = 'args'; +export const TIMESTAMP_PARAM_NAME = 'TS'; export const MUTATION_ARGS = [RESOLVER_PARAM_NAME, PAYLOAD_PARAM_NAME, CONDITION_PARAM_NAME]; // new jsonp export const JSONP_CALLBACK_NAME = 'jsonqlJsonpCallback'; diff --git a/packages/constants/package.json b/packages/constants/package.json index e77c5e21f88c38a2eff459ccabe747c9346fa0ae..7b8a8ac0a5c39a7101a82ea950716d4f33db3fa9 100755 --- a/packages/constants/package.json +++ b/packages/constants/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-constants", - "version": "1.8.11", + "version": "1.8.12", "description": "All the share constants for json:ql tools", "main": "main.js", "module": "module.js", diff --git a/packages/utils/package.json b/packages/utils/package.json index 945b07b46b8493aa866d3d3eb23e4e984977915c..cd023d7eb235810b7d5ac2a541ae6442a096fab2 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-utils", - "version": "0.8.5", + "version": "0.8.6", "description": "This is a jsonql dependency module, not for generate use.", "main": "main.js", "module": "index.js", diff --git a/packages/utils/src/params-api.js b/packages/utils/src/params-api.js index a7ab054234ac214308276136879430df57d64f49..72eda760265f3b1dd30e7288d9e43d2d92dfa54a 100644 --- a/packages/utils/src/params-api.js +++ b/packages/utils/src/params-api.js @@ -13,6 +13,8 @@ import isArray from 'lodash-es/isArray' import isPlainObject from 'lodash-es/isPlainObject' import isString from 'lodash-es/isString' +import { timestamp } from './generic' + /** * make sure it's an object (it was call formatPayload but it doesn't make sense) * @param {*} payload the object comes in could be string based @@ -37,6 +39,19 @@ export function getNameFromPayload(payload) { return Object.keys(payload)[0] } +/** + * wrapper method to add the timestamp as well + * @param {string} resolverName + * @param {*} payload + * @return {object} delierable + */ +export function createDeliverable(resolverName, payload) { + return { + [resolverName]: payload, + timestamp: [ timestamp() ] + } +} + /** * @param {string} resolverName name of function * @param {array} [args=[]] from the ...args @@ -49,7 +64,7 @@ export function createQuery(resolverName, args = [], jsonp = false) { if (jsonp === true) { return payload; } - return { [resolverName]: payload } + return createDeliverable(resolverName, payload) } throw new JsonqlValidationError(`[createQuery] expect resolverName to be string and args to be array!`, { resolverName, args }) } @@ -78,7 +93,7 @@ export function createMutation(resolverName, payload, condition = {}, jsonp = fa return _payload; } if (isString(resolverName)) { - return { [resolverName]: _payload } + return createDeliverable(resolverName, _payload) } throw new JsonqlValidationError(`[createMutation] expect resolverName to be string!`, { resolverName, payload, condition }) } diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json index 4ad3d1659d29f277c07de014eb1988fc747ec536..18e4636d7169f35c3201b4cc0dae052d123a9ef2 100755 --- a/packages/ws-server/package.json +++ b/packages/ws-server/package.json @@ -1,6 +1,6 @@ { "name": "jsonql-ws-server", - "version": "1.4.3", + "version": "1.4.4", "description": "Setup WebSocket server for the jsonql to run on the same host, automatic generate public / private channel using contract", "main": "index.js", "files": [ @@ -32,12 +32,12 @@ "debug": "^4.1.1", "esm": "^3.2.25", "fs-extra": "^8.1.0", - "jsonql-constants": "^1.8.10", + "jsonql-constants": "^1.8.11", "jsonql-errors": "^1.1.6", "jsonql-jwt": "^1.3.4", "jsonql-params-validator": "^1.4.11", - "jsonql-resolver": "^0.9.6", - "jsonql-utils": "^0.8.4", + "jsonql-resolver": "^0.9.9", + "jsonql-utils": "^0.8.5", "lodash": "^4.17.15", "ws": "^7.2.0" }, diff --git a/packages/ws-server/src/core/ws-setup.js b/packages/ws-server/src/core/ws-setup.js index 382768cfa913ef19634201e7272b24d07384652d..f3f460e9faa7de66602f567454df6ffa039e38fa 100644 --- a/packages/ws-server/src/core/ws-setup.js +++ b/packages/ws-server/src/core/ws-setup.js @@ -35,8 +35,7 @@ const fnHandler = (ws, payload, resolverName, params, opts, userdata) => { } // @NOTE the params.params is from the contract return validateAsync(payload.args, params.params, true) - .then( args => { - return resolveMethod( + .then(args => resolveMethod( resolverName, args, // this is the clear value from validateAsync params, @@ -44,7 +43,7 @@ const fnHandler = (ws, payload, resolverName, params, opts, userdata) => { ws, userdata ) - }) + ) .then(result => { debug('result', result) // decide if we need to call the cb or not here diff --git a/packages/ws-server/src/share/add-property.js b/packages/ws-server/src/share/add-property.js index c70c1218cd3b3f1b6b09ca74e0e062fdbb17ef56..a55a11f0d35cfa0c72da37139ada0e7e2f3cb26e 100644 --- a/packages/ws-server/src/share/add-property.js +++ b/packages/ws-server/src/share/add-property.js @@ -1,14 +1,15 @@ // add required properties to the resolver -const _ = require('lodash') const { EMIT_REPLY_TYPE, SEND_MSG_PROP_NAME, ON_MESSAGE_PROP_NAME, - JS_WS_NAME + JS_WS_NAME, + INIT_CLIENT_PROP_KEY } = require('jsonql-constants') // @BUG it's weird this file is not here but no error was throw const { objDefineProps, injectToFn } = require('jsonql-utils') const { provideUserdata } = require('jsonql-jwt') +const { injectNodeClient } = require('jsonql-resolver') const { nil, createWsReply, getDebug } = require('../share/helpers') const debug = getDebug(`addProperty`) @@ -24,26 +25,35 @@ resolver = addHandlerProperty(resolver, ON_MESSAGE_PROP_NAME, function(handler) /** * using the serverType to provide different addProperty method to this + * change to return a promise on 1.4.4 * @param {function} fn the resolver function * @param {string} resolverName resolver name * @param {object} ws the different context object * @param {object|boolean} userdata false when there is none + * @param {object} opts configuration added in 1.4.4 for the client configs * @return {function} the applied function */ -const addProperty = (fn, resolverName, ws, userdata) => { - return _(injectToFn(fn, JS_WS_NAME, ws)) - .chain() - .thru(resolver => { +const addProperty = (fn, resolverName, ws, userdata, opts) => { + return Promise + .resolve(injectToFn(fn, JS_WS_NAME, ws)) + // define the send method + .then(resolver => { debug(`add ${SEND_MSG_PROP_NAME} to ${resolverName}`) return objDefineProps(fn, SEND_MSG_PROP_NAME, function(prop) { // @TODO should this get validate as well? ws.send(createWsReply(EMIT_REPLY_TYPE, resolverName, prop)) }, nil) }) - .thru(resolver => { - return userdata ? provideUserdata(resolver, userdata) : resolver; + .then(resolver => userdata ? provideUserdata(resolver, userdata) : resolver) + .then(resolver => { + if (opts[INIT_CLIENT_PROP_KEY] && opts[INIT_CLIENT_PROP_KEY].then) { + debug(`using INIT_CLIENT_PROP_KEY to add clients to the resolver`) + return opts[INIT_CLIENT_PROP_KEY] + .then(clients => injectNodeClient(resolver, clients)) + } + // @TODO what if we run this standalone and we want to inject clients to it? + return resolver; }) - .value() } module.exports = { addProperty } diff --git a/packages/ws-server/src/share/resolve-method.js b/packages/ws-server/src/share/resolve-method.js index a3729852c56fc71c13d31a0e3894ef7b02a29563..596f921591efb9ea39f11e78f81fec2f5919ec53 100644 --- a/packages/ws-server/src/share/resolve-method.js +++ b/packages/ws-server/src/share/resolve-method.js @@ -32,18 +32,20 @@ const debug = getDebug('resolve-method') * @param {object} opts for search later * @param {object} ws the WebSocket instance * @param {object} [userdata=false] userdata - * @return {mixed} depends on the contract + * @return {promise} depends on the contract */ 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 tfn = addProperty(fn, resolverName, ws, userdata) - try { - return Reflect.apply(tfn, null, args) - } catch(e) { - debug(`resolveMethod Error`, e) - throw new JsonqlResolverAppError(resolverName, e) - } + return addProperty(fn, resolverName, ws, userdata, opts) + .then(tfn => { + try { + return Reflect.apply(tfn, null, args) + } catch(e) { + debug(`resolveMethod Error`, e) + throw new JsonqlResolverAppError(resolverName, e) + } + }) } // we only need to export one method