From 23f19a0df50e21adbdb12150054b26027c4e7050 Mon Sep 17 00:00:00 2001 From: "Michael Bradley, Jr" Date: Sun, 11 Nov 2018 16:43:56 -0600 Subject: [PATCH] fix: runtime environment needs to support locally installed embark Reintroduce NODE_PATH so that DApps with embark locally installed can properly resolve modules supplied by embark. Refactor process.env related settings into src/lib/core/env.js --- embark-ui/package-lock.json | 12 ++-- src/cmd/cmd.js | 28 +-------- src/lib/core/env.js | 67 ++++++++++++++++++++++ src/lib/core/fs.js | 53 +++++------------ src/lib/modules/console/index.js | 11 +++- src/lib/modules/pipeline/webpack.config.js | 40 ++++++------- src/test/fs.js | 1 + 7 files changed, 118 insertions(+), 94 deletions(-) create mode 100644 src/lib/core/env.js diff --git a/embark-ui/package-lock.json b/embark-ui/package-lock.json index 76149d23d..0338da246 100644 --- a/embark-ui/package-lock.json +++ b/embark-ui/package-lock.json @@ -47,9 +47,9 @@ } }, "@types/node": { - "version": "10.12.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz", - "integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ==" + "version": "10.12.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.5.tgz", + "integrity": "sha512-GzdHjq3t3eGLMv92Al90Iq+EoLL+86mPfQhuglbBFO7HiLdC/rkt+zrzJJumAiBF6nsrBWhou22rPW663AAyFw==" }, "abab": { "version": "1.0.4", @@ -2390,9 +2390,9 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cors": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", - "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "requires": { "object-assign": "^4", "vary": "^1" diff --git a/src/cmd/cmd.js b/src/cmd/cmd.js index 38c220837..cf7d3fd47 100644 --- a/src/cmd/cmd.js +++ b/src/cmd/cmd.js @@ -1,33 +1,11 @@ const program = require('commander'); const EmbarkController = require('./cmd_controller.js'); const i18n = require('../lib/core/i18n/i18n.js'); +const fs = require('../lib/core/fs.js'); const utils = require('../lib/utils/utils.js'); let embark = new EmbarkController(); -// set PWD to process.cwd() since Windows doesn't have a value for PWD -if (!process.env.PWD) { - process.env.PWD = process.cwd(); -} - -// set the anchor for embark's fs.dappPath() -if (!process.env.DAPP_PATH) { - process.env.DAPP_PATH = process.env.PWD; -} - -// set the anchor for embark's fs.embarkPath() -if (!process.env.EMBARK_PATH) { - process.env.EMBARK_PATH = utils.joinPath(__dirname, '../..'); -} - -// set the anchor for embark's fs.pkgPath() -if (!process.env.PKG_PATH) { - process.env.PKG_PATH = process.env.PWD; -} - -process.env.DEFAULT_DIAGRAM_PATH = utils.joinPath(process.env.DAPP_PATH, 'diagram.svg'); -process.env.DEFAULT_CMD_HISTORY_SIZE = 20; - class Cmd { constructor() { program.version(embark.version); @@ -308,7 +286,7 @@ class Cmd { .option('--skip-functions', __('Graph will not include functions')) .option('--skip-events', __('Graph will not include events')) .option('--locale [locale]', __('language to use (default: en)')) - .option('--output [svgfile]', __('filepath to output SVG graph to (default: %s)', process.env['DEFAULT_DIAGRAM_PATH'])) + .option('--output [svgfile]', __('filepath to output SVG graph to (default: %s)', fs.diagramPath())) .description(__('generates documentation based on the smart contracts configured')) .action(function(env, options) { i18n.setOrDetectLocale(options.locale); @@ -318,7 +296,7 @@ class Cmd { skipUndeployed: options.skipUndeployed, skipFunctions: options.skipFunctions, skipEvents: options.skipEvents, - output: options.output || process.env['DEFAULT_DIAGRAM_PATH'] + output: options.output || fs.diagramPath() }); }); } diff --git a/src/lib/core/env.js b/src/lib/core/env.js new file mode 100644 index 000000000..3ddac05c9 --- /dev/null +++ b/src/lib/core/env.js @@ -0,0 +1,67 @@ +/* global __dirname module process require */ + +const {delimiter} = require('path'); +const {joinPath} = require('../utils/utils.js'); + +function anchoredValue(anchor, value) { + if (!arguments.length) { + throw new TypeError('anchor name was not specified'); + } + if (arguments.length > 2) { + throw new TypeError('accepts at most 2 arguments'); + } + if (typeof anchor !== 'string') { + throw new TypeError('anchor name was not a string'); + } + let _anchor = process.env[anchor]; + if (arguments.length < 2 && !_anchor) { + throw new Error(`process.env.${anchor} was not set`); + } + // don't override an existing value, e.g. if already set by bin/embark + if (!_anchor) { + _anchor = value; + process.env[anchor] = _anchor; + } + return _anchor; +} + +const PWD = 'PWD'; +const DEFAULT_PWD = process.cwd(); +anchoredValue(PWD, DEFAULT_PWD); + +const DAPP_PATH = 'DAPP_PATH'; +const DEFAULT_DAPP_PATH = anchoredValue(PWD); +anchoredValue(DAPP_PATH, DEFAULT_DAPP_PATH); + +const CMD_HISTORY_SIZE = 'CMD_HISTORY_SIZE'; +const DEFAULT_CMD_HISTORY_SIZE = 20; +anchoredValue(CMD_HISTORY_SIZE, DEFAULT_CMD_HISTORY_SIZE); + +const DIAGRAM_PATH = 'DIAGRAM_PATH'; +const DEFAULT_DIAGRAM_PATH = joinPath(anchoredValue(DAPP_PATH), 'diagram.svg'); +anchoredValue(DIAGRAM_PATH, DEFAULT_DIAGRAM_PATH); + +const EMBARK_PATH = 'EMBARK_PATH'; +const DEFAULT_EMBARK_PATH = joinPath(__dirname, '../../..'); +anchoredValue(EMBARK_PATH, DEFAULT_EMBARK_PATH); + +const PKG_PATH = 'PKG_PATH'; +const DEFAULT_PKG_PATH = anchoredValue(PWD); +anchoredValue(PKG_PATH, DEFAULT_PKG_PATH); + +const NODE_PATH = 'NODE_PATH'; +// NOTE: setting NODE_PATH at runtime won't effect lookup behavior in the +// current process, but will take effect in child processes +process.env[NODE_PATH] = joinPath(anchoredValue(EMBARK_PATH), 'node_modules') + + (process.env[NODE_PATH] ? delimiter : '') + + (process.env[NODE_PATH] || ''); + +module.exports = { + anchoredValue, + PWD, + DAPP_PATH, + CMD_HISTORY_SIZE, + DIAGRAM_PATH, + EMBARK_PATH, + PKG_PATH +}; diff --git a/src/lib/core/fs.js b/src/lib/core/fs.js index 9ab9c61f5..2f2489641 100644 --- a/src/lib/core/fs.js +++ b/src/lib/core/fs.js @@ -3,34 +3,9 @@ const os = require('os'); let path = require('path'); let fs = require('fs-extra'); let utils = require('../utils/utils.js'); +let env = require('./env.js'); require('colors'); -// set PWD to process.cwd() since Windows doesn't have a value for PWD -if (!process.env.PWD) { - process.env.PWD = process.cwd(); -} - -// set the anchor for embark's fs.dappPath() -if (!process.env.DAPP_PATH) { - process.env.DAPP_PATH = process.env.PWD; -} - -// set the anchor for embark's fs.embarkPath() -if (!process.env.EMBARK_PATH) { - process.env.EMBARK_PATH = utils.joinPath(__dirname, '../../..'); -} - -// set the anchor for embark's fs.pkgPath() -if (!process.env.PKG_PATH) { - process.env.PKG_PATH = process.env.PWD; -} - -const pathConfigs = { - DAPP_PATH: process.env.DAPP_PATH, - EMBARK_PATH: process.env.EMBARK_PATH, - PKG_PATH: process.env.PKG_PATH -}; - function restrictPath(receiver, binding, count, args) { const dapp = dappPath(); const embark = embarkPath(); @@ -149,25 +124,24 @@ function removeSync() { return restrictPath(fs.removeSync, fs.removeSync, 1, arguments); } -function anchoredPath(envAnchor, ...args) { - let anchor = pathConfigs[envAnchor]; - if (!pathConfigs[envAnchor]) { - console.error(`process.env.${envAnchor} was not set`.bold.red); - process.exit(1); - } - return utils.joinPath(anchor, ...args); +function anchoredPath(anchor, ...args) { + return utils.joinPath(env.anchoredValue(anchor), ...args); } function embarkPath() { - return anchoredPath('EMBARK_PATH', ...arguments); + return anchoredPath(env.EMBARK_PATH, ...arguments); } function dappPath() { - return anchoredPath('DAPP_PATH', ...arguments); + return anchoredPath(env.DAPP_PATH, ...arguments); +} + +function diagramPath() { + return anchoredPath(env.DIAGRAM_PATH, ...arguments); } function pkgPath() { - return anchoredPath('PKG_PATH', ...arguments); + return anchoredPath(env.PKG_PATH, ...arguments); } function createWriteStream() { @@ -209,8 +183,11 @@ module.exports = { access, appendFileSync, copy, + copyPreserve, copySync, createWriteStream, + dappPath, + diagramPath, embarkPath, existsSync, mkdirp, @@ -218,6 +195,7 @@ module.exports = { move, moveSync, outputFileSync, + pkgPath, readFile, readFileSync, readJSONSync, @@ -231,8 +209,5 @@ module.exports = { writeFile, writeFileSync, writeJSONSync, - copyPreserve, - dappPath, - pkgPath, writeJson }; diff --git a/src/lib/modules/console/index.js b/src/lib/modules/console/index.js index a075f2445..45d3a988b 100644 --- a/src/lib/modules/console/index.js +++ b/src/lib/modules/console/index.js @@ -1,3 +1,4 @@ +let env = require('../../core/env'); let fs = require('../../core/fs'); let utils = require('../../utils/utils'); const EmbarkJS = require('embarkjs'); @@ -23,7 +24,7 @@ class Console { this.ipc.on('console:executeCmd', this.executeCmd.bind(this)); } this.events.setCommandHandler("console:executeCmd", this.executeCmd.bind(this)); - this.events.setCommandHandler("console:history", (cb) => this.getHistory(process.env.DEFAULT_CMD_HISTORY_SIZE, cb)); + this.events.setCommandHandler("console:history", (cb) => this.getHistory(this.cmdHistorySize(), cb)); this.registerEmbarkJs(); this.registerConsoleCommands(); this.registerApi(); @@ -31,6 +32,10 @@ class Console { this.suggestions = new Suggestions(embark, options); } + cmdHistorySize() { + return env.anchoredValue(env.CMD_HISTORY_SIZE); + } + registerApi() { let plugin = this.plugins.createPlugin('consoleApi', {}); plugin.registerAPICall('post', '/embark-api/command', (req, res) => { @@ -170,7 +175,7 @@ class Console { _length = parseInt(_length, 10); if (isNaN(_length)) return callback("Invalid argument. Please provide an integer."); } - let length = _length || process.env.DEFAULT_CMD_HISTORY_SIZE; + let length = _length || this.cmdHistorySize(); return callback(null, this.history .slice(Math.max(0, this.history.length - length)) .filter(line => line.trim()) @@ -182,7 +187,7 @@ class Console { if (fs.existsSync(utils.dirname(this.cmdHistoryFile))) { fs.writeFileSync(this.cmdHistoryFile, this.history - .slice(Math.max(0, this.history.length - process.env.DEFAULT_CMD_HISTORY_SIZE)) + .slice(Math.max(0, this.history.length - this.cmdHistorySize())) .reverse() .filter(line => line.trim()) .join('\n')); diff --git a/src/lib/modules/pipeline/webpack.config.js b/src/lib/modules/pipeline/webpack.config.js index d60591df7..89a0e8954 100644 --- a/src/lib/modules/pipeline/webpack.config.js +++ b/src/lib/modules/pipeline/webpack.config.js @@ -8,25 +8,20 @@ const embarkPath = process.env.EMBARK_PATH; const dappNodeModules = path.join(dappPath, 'node_modules'); const embarkNodeModules = path.join(embarkPath, 'node_modules'); -function customRequire(mod) { - return require(customRequire.resolve(mod)); +function requireFromEmbark(mod) { + return require(requireFromEmbark.resolve(mod)); } -customRequire.resolve = function (mod) { +requireFromEmbark.resolve = function (mod) { return require.resolve( mod, - {paths: [dappNodeModules, embarkNodeModules]} + {paths: [embarkNodeModules]} ); }; -// some packages, plugins, and presets referenced/required in this webpack -// config are deps of embark and will effectively be transitive dapp deps -// unless specified in the dapp's own package.json - -const cloneDeep = customRequire('lodash.clonedeep'); -// const CompressionPlugin = customRequire('compression-webpack-plugin'); -const glob = customRequire('glob'); -const HardSourceWebpackPlugin = customRequire('hard-source-webpack-plugin'); +const cloneDeep = requireFromEmbark('lodash.clonedeep'); +const glob = requireFromEmbark('glob'); +const HardSourceWebpackPlugin = requireFromEmbark('hard-source-webpack-plugin'); const embarkAliases = require(path.join(dappPath, '.embark/embark-aliases.json')); const embarkAssets = require(path.join(dappPath, '.embark/embark-assets.json')); @@ -66,10 +61,10 @@ const entry = Object.keys(embarkAssets) function resolve(pkgName) { if (Array.isArray(pkgName)) { const _pkgName = pkgName[0]; - pkgName[0] = customRequire.resolve(_pkgName); + pkgName[0] = requireFromEmbark.resolve(_pkgName); return pkgName; } - return customRequire.resolve(pkgName); + return requireFromEmbark.resolve(pkgName); } // base config @@ -122,6 +117,11 @@ const base = { ], 'babel-plugin-macros', '@babel/plugin-transform-destructuring', + [ + '@babel/plugin-proposal-decorators', { + legacy: true + } + ], [ '@babel/plugin-proposal-class-properties', { loose: true @@ -187,13 +187,13 @@ const base = { ], modules: [ ...versions, - 'node_modules', + dappNodeModules, embarkNodeModules ] }, resolveLoader: { modules: [ - 'node_modules', + dappNodeModules, embarkNodeModules ] } @@ -209,7 +209,7 @@ const isFlowEnabled = !embarkPipeline.typescript; if (isFlowEnabled) { // position @babel/plugin-transform-flow-strip-types per babel-preset-react-app baseBabelLoader.options.plugins.unshift( - customRequire.resolve('@babel/plugin-transform-flow-strip-types') + requireFromEmbark.resolve('@babel/plugin-transform-flow-strip-types') ); } @@ -222,7 +222,7 @@ if (isTypeScriptEnabled) { // position @babel/preset-typescript as the last preset (runs first) // see: https://blogs.msdn.microsoft.com/typescript/2018/08/27/typescript-and-babel-7/ baseBabelLoader.options.presets.push( - customRequire.resolve('@babel/preset-typescript') + requireFromEmbark.resolve('@babel/preset-typescript') ); // additional extensions baseBabelLoader.test = /\.(js|ts)x?$/; @@ -259,13 +259,11 @@ production.name = 'production'; const prodBabelLoader = production.module.rules[3]; // position babel-plugin-transform-react-remove-prop-types per babel-preset-react-app prodBabelLoader.options.plugins.splice(prodBabelLoader.length - 1, 0, [ - customRequire.resolve('babel-plugin-transform-react-remove-prop-types'), + requireFromEmbark.resolve('babel-plugin-transform-react-remove-prop-types'), { removeImport: true } ]); -// compression of webpack's JS output not enabled by default -// production.plugins.push(new CompressionPlugin()); // export a list of named configs // ----------------------------------------------------------------------------- diff --git a/src/test/fs.js b/src/test/fs.js index dad2f4471..7d41293c8 100644 --- a/src/test/fs.js +++ b/src/test/fs.js @@ -29,6 +29,7 @@ describe('fs', () => { const helperFunctions = [ 'dappPath', + 'diagramPath', 'embarkPath', 'pkgPath', 'tmpDir'