diff --git a/packages/contract-cli/package.json b/packages/contract-cli/package.json index e3f53b610d405b6f85a9814779907615bcf405a8..1193786ff52afbca6c157c1b90c337a1a0b33e2b 100755 --- a/packages/contract-cli/package.json +++ b/packages/contract-cli/package.json @@ -55,7 +55,7 @@ "fs-extra": "^8.1.0", "glob": "^7.1.6", "jsdoc-api": "^5.0.4", - "jsonql-constants": "^2.0.5", + "jsonql-constants": "^2.0.6", "jsonql-errors": "^1.2.1", "jsonql-params-validator": "^1.6.1", "jsonql-utils": "^1.2.4", diff --git a/packages/contract-cli/src/generator/generate-output.js b/packages/contract-cli/src/generator/generate-output.js index 6e726c864d8e46d5a740a5268e81c91bbae871c7..768567c8b8be85a2c2afbc923c2a2fe553d2d4c3 100644 --- a/packages/contract-cli/src/generator/generate-output.js +++ b/packages/contract-cli/src/generator/generate-output.js @@ -11,11 +11,12 @@ const debug = require('debug')('jsonql-contract:generate-output') * Generate the final contract output to file * @param {object} config output directory * @param {object} contract processed result + * @param {boolean} public id if its public or not * @return {boolean} true on success */ -const generateOutput = function(config, contract) { +const generateOutput = function(config, contract, public = false) { - debug('generateOutput configuration', config) + debug(`generateOutput configuration ${public ? '[PUBLIC]' : ''}`, config) // this return a promise interface const { outputFilename, contractDir } = config // resolverDir @@ -23,7 +24,7 @@ const generateOutput = function(config, contract) { // keep or remove the existing contract file return keepOrCleanContract(config, dist) // @1.9.0 add the socket auth part - .then(() => processSocketAuth(config, contract)) + .then(() => processSocketAuth(config, contract, public)) .then(newContract => mutateContract(config, newContract)) .then(finalContract => ( writeFileOut(dist, finalContract) diff --git a/packages/contract-cli/src/generator/get-socket-auth-resolver.js b/packages/contract-cli/src/generator/get-socket-auth-resolver.js index 6d098fb69883c0bfac3f3c3d4b375eefb5a1ee8c..0040fed2eded0164410e36534bfbb1ab8a9b39ce 100644 --- a/packages/contract-cli/src/generator/get-socket-auth-resolver.js +++ b/packages/contract-cli/src/generator/get-socket-auth-resolver.js @@ -5,13 +5,21 @@ const fsx = require('fs-extra') const { join, sep, dirname, basename } = require('path') const { merge } = require('lodash') -const { SOCKET_NAME, AUTH_NAME, EXT, INDEX_KEY, SOCKET_AUTH_NAME } = require('jsonql-constants') +const { chainPromises } = require('jsonql-utils') const { inArray, isObjectHasKey } = require('jsonql-params-validator') +const { + SOCKET_NAME, + AUTH_NAME, + EXT, + INDEX_KEY, + SOCKET_AUTH_NAME +} = require('jsonql-constants') + +const { removeSrvAuthFromContract } = require('../utils') const { getResolverFiles } = require('./read-files-out-contract') const { getSourceType } = require('./get-source-type') const { parseFileToAst } = require('./parse-file-to-ast') -const { chainPromises } = require('jsonql-utils') /** * Return the list of files from the folder first @@ -24,7 +32,7 @@ function getSocketAuthResolverFiles(resolverDir, fileExt = EXT) { if (fsx.existsSync(dir)) { return getResolverFiles(dir, fileExt) } - debug(`${dir} does not existed!`) + console.error(`${dir} does not existed!`) // we don't throw error here just return an empty result return Promise.resolve([]) } @@ -140,13 +148,22 @@ function getSocketAuthResolver(config, sourceType = null, fileExt = EXT) { * This will be the main interface that insert into the generateOutput * @param {object} config configuration * @param {object} contract the already working contract + * @param {boolean} public true then need to filter out some of the things * @return {object} contract with the extra bit */ -function processSocketAuth(config, contract) { +function processSocketAuth(config, contract, public) { if (isObjectHasKey(contract, SOCKET_NAME) && config.enableAuth === true) { const { sourceType } = contract return getSocketAuthResolver(config, sourceType) + .then(partialContract => { + if (public) { + console.info(`is public and call removeSrvAuthFromContract`) + + return removeSrvAuthFromContract(partialContract, SOCKET_AUTH_NAME, config) + } + return partialContract + }) .then(partialContract => ( merge({}, contract, partialContract) )) diff --git a/packages/contract-cli/src/generator/index.js b/packages/contract-cli/src/generator/index.js index 25ee7d4ab24dfb54cb0147d92bd575be6cdd34aa..e67310e5787eb68cfc9741b01cd567e143cf843f 100644 --- a/packages/contract-cli/src/generator/index.js +++ b/packages/contract-cli/src/generator/index.js @@ -48,7 +48,8 @@ const banner = config => { const callPublicGenerator = (config, contract) => ( generateOutput( merge({}, config, { outputFilename: PUBLIC_CONTRACT_FILE_NAME }), - publicContractGenerator(config, contract) + publicContractGenerator(config, contract), + true // add a flag here to id if its public ) ) diff --git a/packages/contract-cli/src/public-contract/index.js b/packages/contract-cli/src/public-contract/index.js index 54f036e4b18c68349505c2b6b4f89e72f990fc2e..124456b6292002182e4affdcdc772e95ed88f1db 100644 --- a/packages/contract-cli/src/public-contract/index.js +++ b/packages/contract-cli/src/public-contract/index.js @@ -10,14 +10,15 @@ const { MUTATION_NAME, AUTH_NAME, SOCKET_AUTH_NAME, - NAMESAPCE_PROP_KEY + NAMESAPCE_PROP_KEY, + FILE_PROP_KEY, + PUBLIC_KEY } = require('jsonql-constants') -// @TODO this should port back to the jsonql-constants -const FILE_PROP_KEY = 'file' const colors = require('colors/safe') -const { getDebug } = require('../utils') +const { getDebug, removeSrvAuthFromContract } = require('../utils') const debug = getDebug('public-contract') + /** * we need to remove the file info from the contract if this is for public * @param {object} json contract @@ -28,9 +29,7 @@ const cleanForPublic = (json, config) => { const { enableAuth, loginHandlerName, - logoutHandlerName, - disconnectHandlerName, - validatorHandlerName + logoutHandlerName } = config for (let type in json) { for (let fn in json[type]) { @@ -39,35 +38,29 @@ const cleanForPublic = (json, config) => { switch (type) { case QUERY_NAME: case MUTATION_NAME: - if (isObjectHasKey(json[type][fn], NAMESAPCE_PROP_KEY) { + if (isObjectHasKey(json[type][fn], NAMESAPCE_PROP_KEY)) { delete json[type][fn][NAMESAPCE_PROP_KEY] } - // @TODO the public key + if (isObjectHasKey(json[type][fn], PUBLIC_KEY)) { + if (!json[type][fn][PUBLIC_KEY]) { + delete json[type][fn][PUBLIC_KEY] + } + } + break + case SOCKET_NAME: // for socket it doesn't care about this key + if (isObjectHasKey(json[type][fn], PUBLIC_KEY)) { + delete json[type][fn][PUBLIC_KEY] + } break default: - + // nothing to do } } } - // also if there is a validator field then delete it - const authValidators = [AUTH_NAME, SOCKET_AUTH_NAME] - for (let i = 0; i < authValidators.length; ++i) { - let av = authValidators[i] - if (json[av]) { - console.log(colors.rainbow(`found ${av}`)) - if (json[av][validatorHandlerName]) { - console.log(`${av} --> ${validatorHandlerName} FOUND?`) - delete json[av][validatorHandlerName] - } else { - console.log(colors.rainbow(`${av} --> ${validatorHandlerName} NOT FOUND?`)) - } - if (json[av][ disconnectHandlerName ]) { - delete json[av][disconnectHandlerName] - } - } else { - console.log(colors.rainbow(`${av} not found???`)) - } - } + // at this point there is no SOCKET_AUT_NAME yet, we need to take this out + json = removeSrvAuthFromContract(json, AUTH_NAME, config) + // it's ugly but fix this later + json = removeSrvAuthFromContract(json, SOCKET_AUTH_NAME, config) // if it's not enableAuth then remove all of these const handlers = [loginHandlerName, logoutHandlerName] if (!enableAuth) { @@ -85,6 +78,7 @@ const cleanForPublic = (json, config) => { return json } + /** * @TODO * using the NODE_ENV to check if there is extra contract file @@ -92,7 +86,7 @@ const cleanForPublic = (json, config) => { * @return {object} empty object when nothing */ function getEnvContractFile(contractDir) { - const nodeEnv = process.env.NODE_ENV; + const nodeEnv = process.env.NODE_ENV const overwriteContractFile = join(contractDir, [nodeEnv, 'json'].join('.')) if (fsx.existsSync(overwriteContractFile)) { debug('found env contract') @@ -110,7 +104,7 @@ function getEnvContractFile(contractDir) { */ function processSocketContract(contractJson, helloContract) { if (contractJson[SOCKET_NAME]) { - debug('processSocketContract', contractJson[SOCKET_NAME]) + // debug('processSocketContract', contractJson[SOCKET_NAME], contractJson[SOCKET_AUTH_NAME]) const helloWorldPart = helloContract[QUERY_NAME] return merge(contractJson, { @@ -128,8 +122,8 @@ function processSocketContract(contractJson, helloContract) { * @return {object} empty then nothing */ function getExpired(config, contractJson) { - const { expired } = config; - const { timestamp } = contractJson; + const { expired } = config + const { timestamp } = contractJson // the timestamp now comes with milsecond ... if (expired && expired > timestamp) { return { expired } @@ -144,27 +138,30 @@ function getExpired(config, contractJson) { * @return {string} json */ function publicContractGenerator(config, contractJson) { - const contractDir = config.contractDir; + /* + const contractDir = config.contractDir if (!contractDir) { throw new JsonqlError('Contract directory is undefined!') } + */ const helloContract = fsx.readJsonSync(join(__dirname, 'hello-world.json')) // env contract file - this should not get written to file // @TODO disable this feature for now and decide if we need it later - const extraContracts = {} + // const extraContracts = {} // const extraContracts = config.raw ? getEnvContractFile(contractDir) : {}; const expiredEntry = getExpired(config, contractJson) - // export - return cleanForPublic( - merge( - {}, - helloContract, - processSocketContract(contractJson, helloContract), - extraContracts, - expiredEntry - ), - config + const contract = merge( + {}, + helloContract, + processSocketContract(contractJson, helloContract), + // extraContracts, + expiredEntry ) + // export + return cleanForPublic(contract, config) } -module.exports = { publicContractGenerator } +module.exports = { + removeSrvAuthFromContract, + publicContractGenerator +} diff --git a/packages/contract-cli/src/utils.js b/packages/contract-cli/src/utils.js index 0eb93484b503abb6bb1dd5cfa97b8a5ecbe24f67..6ec62833cd92cfbfee94735c7265a61277b53073 100644 --- a/packages/contract-cli/src/utils.js +++ b/packages/contract-cli/src/utils.js @@ -1,10 +1,12 @@ // some utils methods const fsx = require('fs-extra') const { extname, resolve } = require('path') -const { isObject } = require('jsonql-params-validator') +const { transform } = require('lodash') + +const { isObject, isObjectHasKey } = require('jsonql-params-validator') const { JsonqlError } = require('jsonql-errors') const { timestamp } = require('jsonql-utils') -const { transform } = require('lodash') +const { SOCKET_AUTH_NAME } = require('jsonql-constants') const checkOptions = require('./options') @@ -53,7 +55,7 @@ const getConfigFromArgs = (config, cmd) => ( case 'remote': // @TODO throw new Error('Not support at the moment!') - + case 'config': // we don't need to do anything here // console.log('config', key, value) @@ -106,8 +108,34 @@ const checkFile = config => { } } + +/** + * ported from the public-contract/index to avoid a circular referenc + * take this out on it's own and also export it for use later + * @param {object} contract to process + * @param {string} key the type key + * @param {object} config for extract the validatorHandlerName + * @return {object} cleaned contract + */ +function removeSrvAuthFromContract(contract, key, config) { + const { disconnectHandlerName, validatorHandlerName } = config + let names = [validatorHandlerName] + if (key === SOCKET_AUTH_NAME) { + names.push(disconnectHandlerName) + } + const ctn = names.length + for (let i = 0; i < ctn; ++i) { + let name = names[i] + if (contract[key] && isObjectHasKey(contract[key], name)) { + delete contract[key][name] + } + } + return contract +} + // export module.exports = { + removeSrvAuthFromContract, getTimestamp, checkFile, applyDefaultOptions, diff --git a/packages/contract-cli/tests/socket.test.js b/packages/contract-cli/tests/socket.test.js index 399b8bee09d92ea857429e7a208f1c4d87d9f9d6..37dfed1cb356a0e145e3821b6a3a3f616039f581 100644 --- a/packages/contract-cli/tests/socket.test.js +++ b/packages/contract-cli/tests/socket.test.js @@ -34,7 +34,7 @@ test.before(async t => { }) test.after(t => { - fsx.removeSync(contractDir) + // fsx.removeSync(contractDir) }) test.cb(`It should able to return a list of socket auth files`, t => { @@ -84,8 +84,8 @@ test.cb(`It should able to generate new entry when socket / auth has content`, t }) }) -test.cb.only(`Now test the public contract with socket`, t => { - t.plan(1) +test.cb(`Now test the public contract with socket`, t => { + t.plan(3) generator({ resolverDir, @@ -95,8 +95,15 @@ test.cb.only(`Now test the public contract with socket`, t => { returnAs: RETURN_AS_JSON }) .then(result => { - t.truthy(result[SOCKET_NAME][HELLO_FN]) + colorDebug('public contract', result) + + t.truthy(result[SOCKET_AUTH_NAME], `It should have the ${SOCKET_AUTH_NAME} part`) + + t.truthy(result[SOCKET_NAME][HELLO_FN], `It should have a ${HELLO_FN} in ${SOCKET_NAME}`) + + t.falsy(result[SOCKET_AUTH_NAME].validator) + t.end() }) })