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
This commit is contained in:
Michael Bradley, Jr 2018-11-11 16:43:56 -06:00 committed by Michael Bradley
parent 53154f8730
commit 23f19a0df5
7 changed files with 118 additions and 94 deletions

View File

@ -47,9 +47,9 @@
} }
}, },
"@types/node": { "@types/node": {
"version": "10.12.0", "version": "10.12.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.5.tgz",
"integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ==" "integrity": "sha512-GzdHjq3t3eGLMv92Al90Iq+EoLL+86mPfQhuglbBFO7HiLdC/rkt+zrzJJumAiBF6nsrBWhou22rPW663AAyFw=="
}, },
"abab": { "abab": {
"version": "1.0.4", "version": "1.0.4",
@ -2390,9 +2390,9 @@
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
}, },
"cors": { "cors": {
"version": "2.8.4", "version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"requires": { "requires": {
"object-assign": "^4", "object-assign": "^4",
"vary": "^1" "vary": "^1"

View File

@ -1,33 +1,11 @@
const program = require('commander'); const program = require('commander');
const EmbarkController = require('./cmd_controller.js'); const EmbarkController = require('./cmd_controller.js');
const i18n = require('../lib/core/i18n/i18n.js'); const i18n = require('../lib/core/i18n/i18n.js');
const fs = require('../lib/core/fs.js');
const utils = require('../lib/utils/utils.js'); const utils = require('../lib/utils/utils.js');
let embark = new EmbarkController(); 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 { class Cmd {
constructor() { constructor() {
program.version(embark.version); program.version(embark.version);
@ -308,7 +286,7 @@ class Cmd {
.option('--skip-functions', __('Graph will not include functions')) .option('--skip-functions', __('Graph will not include functions'))
.option('--skip-events', __('Graph will not include events')) .option('--skip-events', __('Graph will not include events'))
.option('--locale [locale]', __('language to use (default: en)')) .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')) .description(__('generates documentation based on the smart contracts configured'))
.action(function(env, options) { .action(function(env, options) {
i18n.setOrDetectLocale(options.locale); i18n.setOrDetectLocale(options.locale);
@ -318,7 +296,7 @@ class Cmd {
skipUndeployed: options.skipUndeployed, skipUndeployed: options.skipUndeployed,
skipFunctions: options.skipFunctions, skipFunctions: options.skipFunctions,
skipEvents: options.skipEvents, skipEvents: options.skipEvents,
output: options.output || process.env['DEFAULT_DIAGRAM_PATH'] output: options.output || fs.diagramPath()
}); });
}); });
} }

67
src/lib/core/env.js Normal file
View File

@ -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
};

View File

@ -3,34 +3,9 @@ const os = require('os');
let path = require('path'); let path = require('path');
let fs = require('fs-extra'); let fs = require('fs-extra');
let utils = require('../utils/utils.js'); let utils = require('../utils/utils.js');
let env = require('./env.js');
require('colors'); 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) { function restrictPath(receiver, binding, count, args) {
const dapp = dappPath(); const dapp = dappPath();
const embark = embarkPath(); const embark = embarkPath();
@ -149,25 +124,24 @@ function removeSync() {
return restrictPath(fs.removeSync, fs.removeSync, 1, arguments); return restrictPath(fs.removeSync, fs.removeSync, 1, arguments);
} }
function anchoredPath(envAnchor, ...args) { function anchoredPath(anchor, ...args) {
let anchor = pathConfigs[envAnchor]; return utils.joinPath(env.anchoredValue(anchor), ...args);
if (!pathConfigs[envAnchor]) {
console.error(`process.env.${envAnchor} was not set`.bold.red);
process.exit(1);
}
return utils.joinPath(anchor, ...args);
} }
function embarkPath() { function embarkPath() {
return anchoredPath('EMBARK_PATH', ...arguments); return anchoredPath(env.EMBARK_PATH, ...arguments);
} }
function dappPath() { function dappPath() {
return anchoredPath('DAPP_PATH', ...arguments); return anchoredPath(env.DAPP_PATH, ...arguments);
}
function diagramPath() {
return anchoredPath(env.DIAGRAM_PATH, ...arguments);
} }
function pkgPath() { function pkgPath() {
return anchoredPath('PKG_PATH', ...arguments); return anchoredPath(env.PKG_PATH, ...arguments);
} }
function createWriteStream() { function createWriteStream() {
@ -209,8 +183,11 @@ module.exports = {
access, access,
appendFileSync, appendFileSync,
copy, copy,
copyPreserve,
copySync, copySync,
createWriteStream, createWriteStream,
dappPath,
diagramPath,
embarkPath, embarkPath,
existsSync, existsSync,
mkdirp, mkdirp,
@ -218,6 +195,7 @@ module.exports = {
move, move,
moveSync, moveSync,
outputFileSync, outputFileSync,
pkgPath,
readFile, readFile,
readFileSync, readFileSync,
readJSONSync, readJSONSync,
@ -231,8 +209,5 @@ module.exports = {
writeFile, writeFile,
writeFileSync, writeFileSync,
writeJSONSync, writeJSONSync,
copyPreserve,
dappPath,
pkgPath,
writeJson writeJson
}; };

View File

@ -1,3 +1,4 @@
let env = require('../../core/env');
let fs = require('../../core/fs'); let fs = require('../../core/fs');
let utils = require('../../utils/utils'); let utils = require('../../utils/utils');
const EmbarkJS = require('embarkjs'); const EmbarkJS = require('embarkjs');
@ -23,7 +24,7 @@ class Console {
this.ipc.on('console:executeCmd', this.executeCmd.bind(this)); this.ipc.on('console:executeCmd', this.executeCmd.bind(this));
} }
this.events.setCommandHandler("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.registerEmbarkJs();
this.registerConsoleCommands(); this.registerConsoleCommands();
this.registerApi(); this.registerApi();
@ -31,6 +32,10 @@ class Console {
this.suggestions = new Suggestions(embark, options); this.suggestions = new Suggestions(embark, options);
} }
cmdHistorySize() {
return env.anchoredValue(env.CMD_HISTORY_SIZE);
}
registerApi() { registerApi() {
let plugin = this.plugins.createPlugin('consoleApi', {}); let plugin = this.plugins.createPlugin('consoleApi', {});
plugin.registerAPICall('post', '/embark-api/command', (req, res) => { plugin.registerAPICall('post', '/embark-api/command', (req, res) => {
@ -170,7 +175,7 @@ class Console {
_length = parseInt(_length, 10); _length = parseInt(_length, 10);
if (isNaN(_length)) return callback("Invalid argument. Please provide an integer."); 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 return callback(null, this.history
.slice(Math.max(0, this.history.length - length)) .slice(Math.max(0, this.history.length - length))
.filter(line => line.trim()) .filter(line => line.trim())
@ -182,7 +187,7 @@ class Console {
if (fs.existsSync(utils.dirname(this.cmdHistoryFile))) { if (fs.existsSync(utils.dirname(this.cmdHistoryFile))) {
fs.writeFileSync(this.cmdHistoryFile, fs.writeFileSync(this.cmdHistoryFile,
this.history 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() .reverse()
.filter(line => line.trim()) .filter(line => line.trim())
.join('\n')); .join('\n'));

View File

@ -8,25 +8,20 @@ const embarkPath = process.env.EMBARK_PATH;
const dappNodeModules = path.join(dappPath, 'node_modules'); const dappNodeModules = path.join(dappPath, 'node_modules');
const embarkNodeModules = path.join(embarkPath, 'node_modules'); const embarkNodeModules = path.join(embarkPath, 'node_modules');
function customRequire(mod) { function requireFromEmbark(mod) {
return require(customRequire.resolve(mod)); return require(requireFromEmbark.resolve(mod));
} }
customRequire.resolve = function (mod) { requireFromEmbark.resolve = function (mod) {
return require.resolve( return require.resolve(
mod, mod,
{paths: [dappNodeModules, embarkNodeModules]} {paths: [embarkNodeModules]}
); );
}; };
// some packages, plugins, and presets referenced/required in this webpack const cloneDeep = requireFromEmbark('lodash.clonedeep');
// config are deps of embark and will effectively be transitive dapp deps const glob = requireFromEmbark('glob');
// unless specified in the dapp's own package.json const HardSourceWebpackPlugin = requireFromEmbark('hard-source-webpack-plugin');
const cloneDeep = customRequire('lodash.clonedeep');
// const CompressionPlugin = customRequire('compression-webpack-plugin');
const glob = customRequire('glob');
const HardSourceWebpackPlugin = customRequire('hard-source-webpack-plugin');
const embarkAliases = require(path.join(dappPath, '.embark/embark-aliases.json')); const embarkAliases = require(path.join(dappPath, '.embark/embark-aliases.json'));
const embarkAssets = require(path.join(dappPath, '.embark/embark-assets.json')); const embarkAssets = require(path.join(dappPath, '.embark/embark-assets.json'));
@ -66,10 +61,10 @@ const entry = Object.keys(embarkAssets)
function resolve(pkgName) { function resolve(pkgName) {
if (Array.isArray(pkgName)) { if (Array.isArray(pkgName)) {
const _pkgName = pkgName[0]; const _pkgName = pkgName[0];
pkgName[0] = customRequire.resolve(_pkgName); pkgName[0] = requireFromEmbark.resolve(_pkgName);
return pkgName; return pkgName;
} }
return customRequire.resolve(pkgName); return requireFromEmbark.resolve(pkgName);
} }
// base config // base config
@ -122,6 +117,11 @@ const base = {
], ],
'babel-plugin-macros', 'babel-plugin-macros',
'@babel/plugin-transform-destructuring', '@babel/plugin-transform-destructuring',
[
'@babel/plugin-proposal-decorators', {
legacy: true
}
],
[ [
'@babel/plugin-proposal-class-properties', { '@babel/plugin-proposal-class-properties', {
loose: true loose: true
@ -187,13 +187,13 @@ const base = {
], ],
modules: [ modules: [
...versions, ...versions,
'node_modules', dappNodeModules,
embarkNodeModules embarkNodeModules
] ]
}, },
resolveLoader: { resolveLoader: {
modules: [ modules: [
'node_modules', dappNodeModules,
embarkNodeModules embarkNodeModules
] ]
} }
@ -209,7 +209,7 @@ const isFlowEnabled = !embarkPipeline.typescript;
if (isFlowEnabled) { if (isFlowEnabled) {
// position @babel/plugin-transform-flow-strip-types per babel-preset-react-app // position @babel/plugin-transform-flow-strip-types per babel-preset-react-app
baseBabelLoader.options.plugins.unshift( 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) // position @babel/preset-typescript as the last preset (runs first)
// see: https://blogs.msdn.microsoft.com/typescript/2018/08/27/typescript-and-babel-7/ // see: https://blogs.msdn.microsoft.com/typescript/2018/08/27/typescript-and-babel-7/
baseBabelLoader.options.presets.push( baseBabelLoader.options.presets.push(
customRequire.resolve('@babel/preset-typescript') requireFromEmbark.resolve('@babel/preset-typescript')
); );
// additional extensions // additional extensions
baseBabelLoader.test = /\.(js|ts)x?$/; baseBabelLoader.test = /\.(js|ts)x?$/;
@ -259,13 +259,11 @@ production.name = 'production';
const prodBabelLoader = production.module.rules[3]; const prodBabelLoader = production.module.rules[3];
// position babel-plugin-transform-react-remove-prop-types per babel-preset-react-app // position babel-plugin-transform-react-remove-prop-types per babel-preset-react-app
prodBabelLoader.options.plugins.splice(prodBabelLoader.length - 1, 0, [ 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 removeImport: true
} }
]); ]);
// compression of webpack's JS output not enabled by default
// production.plugins.push(new CompressionPlugin());
// export a list of named configs // export a list of named configs
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -29,6 +29,7 @@ describe('fs', () => {
const helperFunctions = [ const helperFunctions = [
'dappPath', 'dappPath',
'diagramPath',
'embarkPath', 'embarkPath',
'pkgPath', 'pkgPath',
'tmpDir' 'tmpDir'