UNPKG

jsonql-contract

Version:

JS API / command line tool to generate the contract.json for jsonql

171 lines (157 loc) 5.33 kB
// porting back from jsonql-koa to grab the NODE_ENV.json and remove the files information to public use const { join } = require('path') const fsx = require('fs-extra') const { merge } = require('lodash') // const { JsonqlError } = require('jsonql-errors') const { isObjectHasKey } = require('jsonql-params-validator') const { SOCKET_NAME, QUERY_NAME, MUTATION_NAME, AUTH_NAME, SOCKET_AUTH_NAME, NAMESAPCE_PROP_KEY, FILE_PROP_KEY, PUBLIC_KEY, STANDALONE_PROP_KEY } = require('jsonql-constants') // const colors = require('colors/safe') 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 * @param {object} config options * @return {string} contract without the file field */ const cleanForPublic = (json, config) => { const { enableAuth, loginHandlerName, logoutHandlerName } = config for (let type in json) { for (let fn in json[type]) { delete json[type][fn][FILE_PROP_KEY] // @TODO for query and mutation we should remove the namespaces etc, they are for socket switch (type) { case QUERY_NAME: case MUTATION_NAME: if (isObjectHasKey(json[type][fn], NAMESAPCE_PROP_KEY)) { delete json[type][fn][NAMESAPCE_PROP_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 } } } // @TODO when socket is not in standalone mode all the auth method // login, logout should not get expose to the client // at this point there is no SOCKET_AUTH_NAME yet, we need to take this out json = removeSrvAuthFromContract(json, AUTH_NAME, config) // this is ugly because it happens in two places, need to refactor this bit at the very end if (config[STANDALONE_PROP_KEY] !== true) { delete json[SOCKET_AUTH_NAME] } else { json = removeSrvAuthFromContract(json, SOCKET_AUTH_NAME, config) } // if it's not enableAuth then remove all of these const handlers = [loginHandlerName, logoutHandlerName] if (!enableAuth) { for (let j = 0; j < handlers.length; ++j) { if (json[AUTH_NAME][handlers[j]]) { delete json[AUTH_NAME][handlers[j]] } } } // @TODO there are several more new features, interceptor, external, plugins, middlewares // don't need this in the public json delete json.sourceType // export return json } /** * @TODO * using the NODE_ENV to check if there is extra contract file * @param {string} contractDir directory store contract * @return {object} empty object when nothing */ function getEnvContractFile(contractDir) { const nodeEnv = process.env.NODE_ENV const overwriteContractFile = join(contractDir, [nodeEnv, 'json'].join('.')) if (fsx.existsSync(overwriteContractFile)) { debug('found env contract') return fsx.readJsonSync(overwriteContractFile) } return {} } /** * When this contract contain a socket field * then we can use this to inject extra into it * @param {object} contractJson the partially generated contract file * @param {object} helloContract the helloWorld contract * @return {object} the contract with socket part added helloWorld (or more later) */ function processSocketContract(contractJson, helloContract) { if (contractJson[SOCKET_NAME]) { // debug('processSocketContract', contractJson[SOCKET_NAME], contractJson[SOCKET_AUTH_NAME]) const helloWorldPart = helloContract[QUERY_NAME] return merge(contractJson, { [SOCKET_NAME]: helloWorldPart }) } return contractJson } /** * add an expired timstamp to the public contract * @param {object} config configuration * @param {object} contractJson the generated contract * @return {object} empty then nothing */ function getExpired(config, contractJson) { const { expired } = config const { timestamp } = contractJson // the timestamp now comes with milsecond ... if (expired && expired > timestamp) { return { expired } } return {} } /** * the actual public contract generator * @param {object} config the original config * @param {object} contractJson the raw json file * @return {string} json */ function publicContractGenerator(config, contractJson) { 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 = config.raw ? getEnvContractFile(contractDir) : {}; const expiredEntry = getExpired(config, contractJson) const contract = merge( {}, helloContract, processSocketContract(contractJson, helloContract), // extraContracts, expiredEntry ) // export return cleanForPublic(contract, config) } module.exports = { removeSrvAuthFromContract, publicContractGenerator }