feat(@embark/utils): introduce setUpEnv() function

This package comes with a `setUpEnv()` function that can be called to
prepare Embark's environment variables for different process contexts.

This allows us to set up Embark's environment within a test runner context
without the requirement of importing `packages/embark/src/lib/core/env.js`,
which happens to set up those necessary environment variables as a side effect.

It's important that a path to `packages/embark`'s root is passed down to `setUpEnv()`
to ensure `EMBARK_PATH` gets the correct value.

E.g. within a package `embark-console`, `setUpEnv()` can be called within its tests
like the following:

```
// packages/embark-console/src/test/console.js

import { joinPath, setUpEnv } from 'embark-utils';

setUpEnv(joinPath(__dirname, '../../../embark'));
```

Here, `__dirname + '../../../embark'` ensures `EMBARK_PATH` points to the root
of `packages/embark`. This might look different in other contexts.

For example calling this function from a test file within `packages/embark`, this would
look like this:

```
// packages/embark/src/test/some_file.js

import { joinPath, setUpEnv } from 'embark-utils';

setUpEnv(joinPath(__dirname, '../../'));
```
This commit is contained in:
Pascal Precht 2019-05-21 14:56:42 +02:00 committed by Pascal Precht
parent 57c3502f1f
commit 038928f8a5
12 changed files with 151 additions and 186 deletions

View File

@ -1,9 +1,12 @@
/*globals describe, it*/
import Console from '../lib';
import Logger from 'embark-logger';
import { joinPath, setUpEnv } from 'embark-utils';
import assert from 'assert';
import { version } from '../../package.json';
setUpEnv(joinPath(__dirname, '../../../embark'));
describe('embark.Console', function() {
let logger = new Logger({logLevel: 'error'});
let ipc = {

View File

@ -5,10 +5,13 @@ declare module "embark-utils" {
prepareForCompilation(isCoverage?: boolean): any;
}
function anchoredValue(anchor: string|null, value: string): string;
function anchoredPath(anchor: string|null, ...args: string[]): string;
function compact(array: any): any;
function checkIsAvailable(url: string, callback: any): void;
function dockerHostSwap(host: string): string;
function dappPath(...names: string[]): string;
function diagramPath(...names: string[]): string;
function escapeHtml(message: any): string;
function embarkPath(...names: string[]): string;
function exit(code?: any): void;
@ -17,5 +20,6 @@ declare module "embark-utils" {
function fuzzySearch(text: string, list: any, filter: any): any;
function getExternalContractUrl(file: string, provideUrl: string): string;
function recursiveMerge(target: any, source: any): any;
function pkgPath(...names: string[]): string;
function removePureView(dir: string): void;
}

View File

@ -0,0 +1,49 @@
import {
anchoredValue,
joinPath,
PWD,
DAPP_PATH,
DIAGRAM_PATH,
EMBARK_PATH,
PKG_PATH,
NODE_PATH
} from './pathUtils';
import * as findUp from 'find-up';
import { delimiter } from 'path';
export function setUpEnv(defaultEmbarkPath) {
const DEFAULT_PWD = process.cwd();
anchoredValue(PWD, DEFAULT_PWD);
const DEFAULT_DAPP_PATH = anchoredValue(PWD);
anchoredValue(DAPP_PATH, DEFAULT_DAPP_PATH);
const DEFAULT_DIAGRAM_PATH = joinPath(anchoredValue(DAPP_PATH), 'diagram.svg');
anchoredValue(DIAGRAM_PATH, DEFAULT_DIAGRAM_PATH);
const DEFAULT_EMBARK_PATH = defaultEmbarkPath;
anchoredValue(EMBARK_PATH, DEFAULT_EMBARK_PATH);
const DEFAULT_PKG_PATH = anchoredValue(PWD);
anchoredValue(PKG_PATH, DEFAULT_PKG_PATH);
const EMBARK_NODE_MODULES_PATHS = [];
let len = 0;
let start = anchoredValue(EMBARK_PATH);
// eslint-disable-next-line no-constant-condition
while (true) {
const found = findUp.sync('node_modules', {cwd: start});
if (!found) break;
start = joinPath(start, '..');
if (EMBARK_NODE_MODULES_PATHS[len - 1] !== found) {
len = EMBARK_NODE_MODULES_PATHS.push(found);
}
}
// 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] = EMBARK_NODE_MODULES_PATHS.join(delimiter) +
(process.env[NODE_PATH] ? delimiter : '') +
(process.env[NODE_PATH] || '');
}

View File

@ -23,7 +23,24 @@ import {
import { getAddressToContract, getTransactionParams } from './transactionUtils';
import LongRunningProcessTimer from './longRunningProcessTimer';
import AccountParser from './accountParser';
import { dappPath, embarkPath, ipcPath, joinPath, tmpDir, urlJoin } from './pathUtils';
import {
anchoredValue,
dappPath,
diagramPath,
embarkPath,
ipcPath,
joinPath,
pkgPath,
tmpDir,
urlJoin,
PWD,
DAPP_PATH,
DIAGRAM_PATH,
EMBARK_PATH,
PKG_PATH,
NODE_PATH
} from './pathUtils';
import { setUpEnv } from './env';
const { extendZeroAddressShorthand, replaceZeroAddressShorthand } = AddressUtils;
@ -244,6 +261,7 @@ function errorMessage(e) {
const Utils = {
anchoredValue,
buildUrl,
buildUrlFromConfig,
joinPath,
@ -257,6 +275,7 @@ const Utils = {
canonicalHost,
compact,
copyToClipboard,
diagramPath,
deconstructUrl,
defaultCorsHost,
defaultHost,
@ -282,6 +301,7 @@ const Utils = {
getHexBalanceFromString,
getExternalContractUrl,
groupBy,
setUpEnv,
sha512,
sha3,
timer,
@ -294,12 +314,19 @@ const Utils = {
normalizeInput: logUtils.normalizeInput,
LogHandler: require('./logHandler'),
LongRunningProcessTimer,
pkgPath,
prepareForCompilation,
proposeAlternative,
toChecksumAddress,
toposort,
AddressUtils,
AccountParser
AccountParser,
PWD,
DAPP_PATH,
DIAGRAM_PATH,
EMBARK_PATH,
PKG_PATH,
NODE_PATH
};
module.exports = Utils;

View File

@ -2,15 +2,51 @@ import * as path from 'path';
import * as os from 'os';
import { sha512 } from './web3Utils';
export const PWD = 'PWD';
export const DAPP_PATH = 'DAPP_PATH';
export const DIAGRAM_PATH = 'DIAGRAM_PATH';
export const EMBARK_PATH = 'EMBARK_PATH';
export const PKG_PATH = 'PKG_PATH';
export const NODE_PATH = 'NODE_PATH';
export function anchoredValue(anchor, value) {
if (!arguments.length) {
throw new TypeError(`anchor name '${anchor}' was not specified`);
}
if (arguments.length > 2) {
throw new TypeError(`accepts at most 2 arguments`);
}
if (typeof anchor !== 'string') {
throw new TypeError(`anchor name '${anchor}' 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;
}
export function anchoredPath(anchor, ...args) {
return joinPath(
anchoredValue(anchor),
...args.map(path => path.replace(dappPath(), ''))
);
}
export function joinPath() {
return path.join.apply(path.join, arguments);
}
export function tmpDir(...args) { return joinPath(os.tmpdir(), ...args); }
export function dappPath(...names) {
return path.join(process.env.DAPP_PATH || process.cwd(), ...names);
}
export function diagramPath(...args) { return anchoredPath(DIAGRAM_PATH, ...args); }
export function pkgPath(...args) { return anchoredPath(PKG_PATH, ...args); }
export function dappPath(...args) { return anchoredPath(DAPP_PATH, ...args); }
export function embarkPath(...args) { return anchoredPath(EMBARK_PATH, ...args); }
export function ipcPath(basename, usePipePathOnWindows = false) {
if (!(basename && typeof basename === 'string')) {
@ -25,14 +61,6 @@ export function ipcPath(basename, usePipePathOnWindows = false) {
);
}
export function embarkPath(...names) {
const EMBARK_PATH = process.env.EMBARK_PATH;
if (!EMBARK_PATH) {
throw new Error('environment variable EMBARK_PATH was not set');
}
return path.join(EMBARK_PATH, ...names);
}
export function urlJoin(url, path) {
let urlChunks = url.split('/');
let levels = path.split('../');

View File

@ -1,4 +1,5 @@
import { __, setOrDetectLocale } from 'embark-i18n';
import { diagramPath } from 'embark-utils';
const program = require('commander');
const EmbarkController = require('./cmd_controller.js');
const fs = require('../lib/core/fs.js');
@ -307,7 +308,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)', fs.diagramPath()))
.option('--output [svgfile]', __('filepath to output SVG graph to (default: %s)', diagramPath()))
.description(__('generates documentation based on the smart contracts configured'))
.action(function(env, options) {
setOrDetectLocale(options.locale);
@ -317,7 +318,7 @@ class Cmd {
skipUndeployed: options.skipUndeployed,
skipFunctions: options.skipFunctions,
skipEvents: options.skipEvents,
output: options.output || fs.diagramPath()
output: options.output || diagramPath()
});
});
}

View File

@ -1,76 +1,3 @@
/* global __dirname module process require */
import { joinPath, setUpEnv } from 'embark-utils';
const {delimiter} = require('path');
const findUp = require('find-up');
import {joinPath} from 'embark-utils';
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 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 EMBARK_NODE_MODULES_PATHS = [];
let len = 0;
let start = anchoredValue(EMBARK_PATH);
// eslint-disable-next-line no-constant-condition
while (true) {
const found = findUp.sync('node_modules', {cwd: start});
if (!found) break;
start = joinPath(start, '..');
if (EMBARK_NODE_MODULES_PATHS[len - 1] !== found) {
len = EMBARK_NODE_MODULES_PATHS.push(found);
}
}
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] = EMBARK_NODE_MODULES_PATHS.join(delimiter) +
(process.env[NODE_PATH] ? delimiter : '') +
(process.env[NODE_PATH] || '');
module.exports = {
anchoredValue,
PWD,
DAPP_PATH,
DIAGRAM_PATH,
EMBARK_PATH,
PKG_PATH
};
setUpEnv(joinPath(__dirname, '../../../'));

View File

@ -1,15 +1,11 @@
/* global module process require */
const {DAPP_PATH,
DIAGRAM_PATH,
EMBARK_PATH,
PKG_PATH,
anchoredValue} = require('./env');
const fs = require('fs-extra');
const os = require('os');
const parseJson = require('parse-json');
const path = require('path');
import {joinPath, sha512} from 'embark-utils';
import { joinPath } from 'embark-utils';
import './env';
require('colors');
function mkdirpSync(...args) { return fs.mkdirpSync(...args); }
@ -73,38 +69,8 @@ function access(...args) { return fs.access(...args); }
function removeSync(...args) { return fs.removeSync(...args); }
function anchoredPath(anchor, ...args) {
return joinPath(
anchoredValue(anchor),
...args.map(path => path.replace(dappPath(), ''))
);
}
function embarkPath(...args) { return anchoredPath(EMBARK_PATH, ...args); }
function dappPath(...args) { return anchoredPath(DAPP_PATH, ...args); }
function diagramPath(...args) { return anchoredPath(DIAGRAM_PATH, ...args); }
function ipcPath(basename, usePipePathOnWindows = false) {
if (!(basename && typeof basename === 'string')) {
throw new TypeError('first argument must be a non-empty string');
}
if (process.platform === 'win32' && usePipePathOnWindows) {
return `\\\\.\\pipe\\${basename}`;
}
return joinPath(
tmpDir(`embark-${sha512(dappPath()).slice(0, 8)}`),
basename
);
}
function pkgPath(...args) { return anchoredPath(PKG_PATH, ...args); }
function createWriteStream(...args) { return fs.createWriteStream(...args); }
function tmpDir(...args) { return joinPath(os.tmpdir(), ...args); }
function copyPreserve(sourceFilePath, targetFilePath) {
const implementation = (sourceFilePath, targetFilePath) => {
let ext = 1;
@ -135,20 +101,15 @@ module.exports = {
copyPreserve,
copySync,
createWriteStream,
dappPath,
diagramPath,
embarkPath,
existsSync,
ensureFileSync,
ensureDirSync,
ipcPath,
mkdirp,
mkdirpSync,
move,
moveSync,
outputFileSync,
outputJSONSync,
pkgPath,
readFile,
readFileSync,
readJSONSync,
@ -159,7 +120,6 @@ module.exports = {
stat,
statSync,
symlink,
tmpDir,
writeFile,
writeFileSync,
writeJSONSync,

View File

@ -1,15 +1,9 @@
/* global module process require */
const {DAPP_PATH,
DIAGRAM_PATH,
EMBARK_PATH,
PKG_PATH,
anchoredValue} = require('../../core/env');
const fs = require('fs-extra');
const os = require('os');
const parseJson = require('parse-json');
const path = require('path');
import {joinPath, sha512} from 'embark-utils';
import { dappPath, embarkPath, joinPath, pkgPath } from 'embark-utils';
require('colors');
function restrictPath(receiver, binding, count, args) {
@ -101,38 +95,8 @@ function access(...args) { return restrictPath(fs.access, fs, 1, args); }
function removeSync(...args) { return restrictPath(fs.removeSync, fs, 1, args); }
function anchoredPath(anchor, ...args) {
return joinPath(
anchoredValue(anchor),
...args.map(path => path.replace(dappPath(), ''))
);
}
function embarkPath(...args) { return anchoredPath(EMBARK_PATH, ...args); }
function dappPath(...args) { return anchoredPath(DAPP_PATH, ...args); }
function diagramPath(...args) { return anchoredPath(DIAGRAM_PATH, ...args); }
function ipcPath(basename, usePipePathOnWindows = false) {
if (!(basename && typeof basename === 'string')) {
throw new TypeError('first argument must be a non-empty string');
}
if (process.platform === 'win32' && usePipePathOnWindows) {
return `\\\\.\\pipe\\${basename}`;
}
return joinPath(
tmpDir(`embark-${sha512(dappPath()).slice(0, 8)}`),
basename
);
}
function pkgPath(...args) { return anchoredPath(PKG_PATH, ...args); }
function createWriteStream(...args) { return restrictPath(fs.createWriteStream, fs, 1, args); }
function tmpDir(...args) { return joinPath(os.tmpdir(), ...args); }
function copyPreserve(sourceFilePath, targetFilePath) {
const implementation = (sourceFilePath, targetFilePath) => {
let ext = 1;
@ -163,20 +127,15 @@ module.exports = {
copyPreserve,
copySync,
createWriteStream,
dappPath,
diagramPath,
embarkPath,
existsSync,
ensureFileSync,
ensureDirSync,
ipcPath,
mkdirp,
mkdirpSync,
move,
moveSync,
outputFileSync,
outputJSONSync,
pkgPath,
readFile,
readFileSync,
readJSONSync,
@ -187,7 +146,6 @@ module.exports = {
stat,
statSync,
symlink,
tmpDir,
writeFile,
writeFileSync,
writeJSONSync,

View File

@ -2,9 +2,8 @@ import { each } from "async";
import { Callback, Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark";
import { NodeVM, NodeVMOptions } from "vm2";
import { compact, recursiveMerge } from "embark-utils";
import { compact, dappPath, recursiveMerge } from "embark-utils";
const fs = require("./fs");
const path = require("path");
const { isEs6Module } = require("../../utils/utils");
@ -51,7 +50,7 @@ class VM {
"rxjs/operators",
],
},
sandbox: { __dirname: fs.dappPath() },
sandbox: { __dirname: dappPath() },
};
/**

View File

@ -3,7 +3,14 @@ const findUp = require('find-up');
const fs = require('../core/fs.js');
const hostedGitInfo = require('hosted-git-info');
const utils = require('./utils.js');
import { embarkPath, downloadFile, joinPath, runCmd, errorMessage } from 'embark-utils';
import {
embarkPath,
downloadFile,
joinPath,
runCmd,
tmpDir as tmpDirUtil,
errorMessage
} from 'embark-utils';
const semver = require('semver');
const {promisify} = require('util');
const {execSync} = require('child_process');
@ -58,7 +65,7 @@ class TemplateGenerator {
process.exit(1);
}
let {url, filePath, browse} = ext;
let tmpFilePath = fs.tmpDir(filePath);
let tmpFilePath = tmpDirUtil(filePath);
try {
try {
await this.download(url, tmpFilePath, browse);
@ -67,7 +74,7 @@ class TemplateGenerator {
if (url_fallback) {
console.log(__('Retrying with the default branch...').yellow);
console.log((__(`It may not be compatible with your Embark version`) + ` ${embarkVersion}`).yellow);
tmpFilePath = fs.tmpDir(filePath_fallback);
tmpFilePath = tmpDirUtil(filePath_fallback);
await this.download(url_fallback, tmpFilePath, browse_fallback);
} else {
throw new Error();

View File

@ -1,7 +1,9 @@
/*globals describe, it*/
const { dappPath, File, Types } = require('embark-utils');
const {expect} = require("chai");
const fs = require("../lib/core/fs");
const { dappPath, File, joinPath, setUpEnv, Types } = require('embark-utils');
const { expect } = require("chai");
const fs = require("fs-extra");
setUpEnv(joinPath(__dirname, '../../'));
describe('embark.File', function () {
describe('Read file contents', function () {