refactor(@embark/core): move Engine into embark-core

This also moves other modules and packages into `embark-core` which are
affected by the move of `Engine`.

It did some clean-up of some modules (e.g. `lib/utils/utils.js` had a lot of
stuff that was not used anywhere).

This is the first step to start typing our core inside out. For now we're just
moving code into their dedicated package, after that we can address making
use of TypeScript features as we see fit.
This commit is contained in:
Pascal Precht 2019-10-30 15:36:21 +01:00
parent 6afe1ace08
commit 96b6dd27c0
No known key found for this signature in database
GPG Key ID: 0EE28D8D6FD85D7D
86 changed files with 3436 additions and 3553 deletions

View File

@ -22,6 +22,8 @@ module.exports = (api) => {
['@babel/plugin-proposal-decorators', { ['@babel/plugin-proposal-decorators', {
legacy: true legacy: true
}], }],
'@babel/plugin-proposal-export-namespace-from',
'@babel/plugin-proposal-export-default-from',
'@babel/plugin-syntax-dynamic-import', '@babel/plugin-syntax-dynamic-import',
['@babel/plugin-proposal-class-properties', { ['@babel/plugin-proposal-class-properties', {
loose: true loose: true

View File

@ -52,6 +52,8 @@
"core-js": "3.3.5", "core-js": "3.3.5",
"embark-utils": "^5.0.0-alpha.1", "embark-utils": "^5.0.0-alpha.1",
"embarkjs": "^5.0.0-alpha.1", "embarkjs": "^5.0.0-alpha.1",
"embark-core": "^5.0.0-alpha.1",
"embark-logger": "^5.0.0-alpha.1",
"fs-extra": "8.1.0", "fs-extra": "8.1.0",
"parse-json": "4.0.0", "parse-json": "4.0.0",
"vm2": "3.6.4", "vm2": "3.6.4",

View File

@ -1,11 +1,11 @@
import { Callback, Embark, Events } /* supplied by @types/embark in packages/embark-typings */ from "embark";
import { __ } from "embark-i18n"; import { __ } from "embark-i18n";
import { Logger } from 'embark-logger';
import * as fs from "./fs"; import * as fs from "./fs";
import VM from "./vm"; import VM from "./vm";
export { fs, VM }; export { fs, VM };
import { Callback, Embark, Events, Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark";
class CodeRunner { class CodeRunner {
private logger: Logger; private logger: Logger;
private events: Events; private events: Events;

View File

@ -1,6 +1,7 @@
import { each } from "async"; import { each } from "async";
import { Callback, Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark"; import { Callback } /* supplied by @types/embark in packages/embark-typings */ from "embark";
import { compact, dappPath, isEs6Module, recursiveMerge } from "embark-utils"; import { compact, dappPath, isEs6Module, recursiveMerge } from "embark-utils";
import { Logger } from 'embark-logger';
import * as path from "path"; import * as path from "path";
import { NodeVM, NodeVMOptions } from "vm2"; import { NodeVM, NodeVMOptions } from "vm2";

View File

@ -50,8 +50,8 @@ class Console {
this.executeCmd(cmd, (err: any, result: any) => { this.executeCmd(cmd, (err: any, result: any) => {
if (err) { if (err) {
// reformat for IPC reply // reformat for IPC reply
err = { name: "Console error", message: err, stack: err.stack }; const error = { name: "Console error", message: err, stack: err.stack };
return cb(err); return cb(error);
} }
cb(null, util.inspect(result)); cb(null, util.inspect(result));
}); });
@ -178,7 +178,7 @@ class Console {
this.saveHistory(cmd); this.saveHistory(cmd);
} }
const plugins = this.plugins.getPluginsProperty("console", "console"); const plugins = this.plugins.getPluginsProperty("console", "console");
const helpDescriptions = []; const helpDescriptions: any[] = [];
for (const plugin of plugins) { for (const plugin of plugins) {
if (plugin.description) { if (plugin.description) {
helpDescriptions.push({ helpDescriptions.push({

View File

@ -1,6 +1,6 @@
/*globals describe, it*/ /*globals describe, it*/
import Console from '../lib'; import Console from '../lib';
import Logger from 'embark-logger'; import { Logger } from 'embark-logger';
import { joinPath, setUpEnv } from 'embark-utils'; import { joinPath, setUpEnv } from 'embark-utils';
import assert from 'assert'; import assert from 'assert';
import { version } from '../../package.json'; import { version } from '../../package.json';

View File

@ -34,29 +34,44 @@
"_build": "npm run solo -- build", "_build": "npm run solo -- build",
"ci": "npm run qa", "ci": "npm run qa",
"clean": "npm run reset", "clean": "npm run reset",
"lint": "eslint process.js src/", "lint": "npm-run-all lint:*",
"qa": "npm-run-all lint _build", "lint:js": "eslint process.js src/",
"// lint:ts": "tslint -c tslint.json \"src/**/*.ts\"",
"qa": "npm-run-all lint typecheck _build",
"reset": "npx rimraf dist embark-*.tgz package", "reset": "npx rimraf dist embark-*.tgz package",
"solo": "embark-solo" "solo": "embark-solo",
"typecheck": "tsc"
}, },
"eslintConfig": { "eslintConfig": {
"extends": "../../../.eslintrc.json" "extends": "../../../.eslintrc.json"
}, },
"dependencies": { "dependencies": {
"@babel/runtime-corejs3": "7.6.3", "@babel/runtime-corejs3": "7.6.3",
"colors": "1.3.2",
"core-js": "3.3.5", "core-js": "3.3.5",
"embark-i18n": "^5.0.0-alpha.1", "embark-i18n": "^5.0.0-alpha.1",
"embark-utils": "^5.0.0-alpha.1", "embark-utils": "^5.0.0-alpha.1",
"embark-logger": "^5.0.0-alpha.1",
"decompress": "4.2.0",
"flatted": "0.2.3", "flatted": "0.2.3",
"fs-extra": "8.1.0", "fs-extra": "8.1.0",
"globule": "1.2.1",
"lodash.clonedeep": "4.5.0",
"node-ipc": "9.1.1", "node-ipc": "9.1.1",
"uuid": "3.3.2" "parse-json": "4.0.0",
"shelljs": "0.8.3",
"uuid": "3.3.2",
"window-size": "1.1.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.6.4",
"babel-jest": "24.9.0",
"embark-solo": "^5.0.0-alpha.0", "embark-solo": "^5.0.0-alpha.0",
"eslint": "5.7.0", "eslint": "5.7.0",
"npm-run-all": "4.1.5", "npm-run-all": "4.1.5",
"rimraf": "3.0.0" "rimraf": "3.0.0",
"tslint": "5.16.0",
"typescript": "3.6.3"
}, },
"engines": { "engines": {
"node": ">=10.17.0 <12.0.0", "node": ">=10.17.0 <12.0.0",

View File

@ -0,0 +1,761 @@
import * as fs from './fs';
import { Plugins } from './plugins';
import { Plugin } from './plugin';
import { EmbarkEmitter as Events } from './events';
import { filesMatchingPattern, fileMatchesPattern } from './utils/utils';
const path = require('path');
const deepEqual = require('deep-equal');
const web3 = require('web3');
const constants = require('embark-core/constants');
import { __ } from 'embark-i18n';
import {
buildUrlFromConfig,
canonicalHost,
dappPath,
defaultHost,
File,
Types,
recursiveMerge,
AddressUtils,
unitRegex,
getWeiBalanceFromString,
prepareContractsConfig,
getExternalContractUrl
} from 'embark-utils';
import { Logger } from 'embark-logger';
const cloneDeep = require('lodash.clonedeep');
const { replaceZeroAddressShorthand } = AddressUtils;
import { getBlockchainDefaults, getContractDefaults } from './configDefaults';
const DEFAULT_CONFIG_PATH = 'config/';
const embark5ChangesUrl = 'https://embark.status.im/docs/migrating_from_3.x.html#Updating-to-v5';
export class Config {
env = 'default';
blockchainConfig: any = {};
contractsConfig: any = {};
pipelineConfig: any = {};
namesystemConfig: any = {};
communicationConfig: any = {};
webServerConfig: any;
storageConfig: any;
chainTracker: any = {};
assetFiles: any = {};
contractsFiles: File[] = [];
configDir: string;
chainsFile = './chains.json';
plugins: Plugins;
logger: Logger;
package: any;
events: Events;
embarkConfig: any = {};
context: any;
version: string;
shownNoAccountConfigMsg = false; // flag to ensure "no account config" message is only displayed once to the user
corsParts: string[] = [];
providerUrl = null;
contractDirectories: string[] = [];
buildDir: any;
dappPath = dappPath;
constructor(options) {
this.env = options.env || 'default';
this.webServerConfig = options.webServerConfig;
this.configDir = options.configDir || DEFAULT_CONFIG_PATH;
this.chainsFile = options.chainsFile;
this.plugins = options.plugins;
this.logger = options.logger;
this.package = options.package;
this.events = options.events;
this.context = options.context || [constants.contexts.any];
this.version = options.version;
this.registerEvents();
}
setConfig(configName, newConfig, cb) {
this[configName] = newConfig;
cb();
}
registerEvents() {
this.events.setCommandHandler("config:cors:add", (url) => {
this.corsParts.push(url);
this._updateBlockchainCors();
});
this.events.setCommandHandler("config:contractsConfig", (cb) => {
cb(null, this.contractsConfig);
});
this.events.setCommandHandler("config:storageConfig", (cb) => {
cb(null, this.storageConfig);
});
this.events.setCommandHandler("config:contractsConfig:set", this.setConfig.bind(this, 'contractsConfig'));
this.events.setCommandHandler("config:blockchainConfig:set", this.setConfig.bind(this, 'blockchainConfig'));
this.events.setCommandHandler("config:storageConfig:set", this.setConfig.bind(this, 'storageConfig'));
this.events.setCommandHandler("config:namesystemConfig:set", this.setConfig.bind(this, 'namesystemConfig'));
this.events.setCommandHandler("config:communicationConfig:set", this.setConfig.bind(this, 'communicationConfig'));
this.events.setCommandHandler("config:contractsFiles", (cb) => {
cb(null, this.contractsFiles);
});
// TODO: refactor this so reading the file can be done with a normal resolver or something that takes advantage of the plugin api
this.events.setCommandHandler("config:contractsFiles:add", (filename, resolver) => {
resolver = resolver || function(callback) { callback(fs.readFileSync(filename).toString()); };
this.contractsFiles.push(new File({path: filename, originalPath: filename, type: Types.custom, resolver}));
});
this.events.setCommandHandler("config:contractsFiles:reset", (cb) => {
this.contractsFiles.forEach((file) => {
if (file.path.includes(".embark")) {
fs.removeSync(file.path);
}
this.contractsFiles = this.contractsFiles.filter((contractFile) => contractFile.path !== file.path);
});
cb();
});
this.events.on('file-remove', (fileType, removedPath) => {
if (fileType !== 'contract') {
return;
}
const normalizedPath = path.normalize(removedPath);
this.contractsFiles = this.contractsFiles.filter(file => path.normalize(file.path) !== normalizedPath);
});
}
loadConfigFiles(options) {
let interceptLogs = options.interceptLogs;
if (options.interceptLogs === undefined) {
interceptLogs = true;
}
if (!fs.existsSync(options.embarkConfig)) {
this.logger.error(__('Cannot find file %s Please ensure you are running this command inside the Dapp folder', options.embarkConfig));
process.exit(1);
}
this.embarkConfig = fs.readJSONSync(options.embarkConfig);
this.embarkConfig.plugins = this.embarkConfig.plugins || {};
this.plugins = new Plugins({
plugins: this.embarkConfig.plugins,
logger: this.logger,
interceptLogs,
events: this.events,
config: this,
context: this.context,
env: this.env,
version: this.version
});
this.plugins.loadPlugins();
this.loadEmbarkConfigFile();
this.loadBlockchainConfigFile();
this.loadStorageConfigFile();
this.loadContractFiles();
this.loadCommunicationConfigFile();
this.loadNameSystemConfigFile();
this.loadPipelineConfigFile();
this.loadAssetFiles();
this.loadContractsConfigFile();
this.loadExternalContractsFiles();
this.loadWebServerConfigFile();
this.loadPluginContractFiles();
this._updateBlockchainCors();
}
reloadConfig() {
this.loadEmbarkConfigFile();
this.loadBlockchainConfigFile();
this.loadStorageConfigFile();
this.loadContractFiles();
this.loadCommunicationConfigFile();
this.loadNameSystemConfigFile();
this.loadPipelineConfigFile();
this.loadAssetFiles();
this.loadContractsConfigFile();
this.loadExternalContractsFiles();
this._updateBlockchainCors();
}
loadContractFiles() {
const loadedContractFiles = this.loadFiles(this.embarkConfig.contracts);
// `this.contractsFiles` could've been mutated at runtime using
// either `config:contractsFiles:add` event or through calls to
// `loadExternalContractsFiles()`, so we have to make sure we preserve
// those added files before we reset `this.contractsFiles`.
//
// We do that by determining the difference between `loadedContractFiles` and the ones
// already in memory in `this.contractsFiles`.
const addedContractFiles = this.contractsFiles.filter(existingFile => !loadedContractFiles.some(file => file.originalPath === existingFile.originalPath));
this.contractsFiles = loadedContractFiles.concat(addedContractFiles);
}
_updateBlockchainCors() {
const blockchainConfig = this.blockchainConfig;
const storageConfig = this.storageConfig;
const webServerConfig = this.webServerConfig;
let corsParts = cloneDeep(this.corsParts);
if (blockchainConfig.isDev) {
corsParts.push('*');
}
if (webServerConfig && webServerConfig.host) {
corsParts.push(buildUrlFromConfig(webServerConfig));
}
if (storageConfig && storageConfig.enabled) {
// if getUrl is specified in the config, that needs to be included in cors
// instead of the concatenated protocol://host:port
if (storageConfig.upload.getUrl) {
// remove /ipfs or /bzz: from getUrl if it's there
let getUrlParts = storageConfig.upload.getUrl.split('/');
getUrlParts = getUrlParts.slice(0, 3);
const host = canonicalHost(getUrlParts[2].split(':')[0]);
const port = getUrlParts[2].split(':')[1];
getUrlParts[2] = port ? [host, port].join(':') : host;
corsParts.push(getUrlParts.join('/'));
} else {
corsParts.push(buildUrlFromConfig(storageConfig.upload));
}
}
// Add cors for the proxy and whisper
corsParts.push(constants.embarkResourceOrigin);
corsParts = Array.from(new Set(corsParts));
this.corsParts = corsParts;
const cors = corsParts.join(',');
if (blockchainConfig.rpcCorsDomain === 'auto') {
blockchainConfig.rpcCorsDomain = cors;
} else if (typeof blockchainConfig.rpcCorsDomain === 'object') {
let tempCors = blockchainConfig.rpcCorsDomain.auto ? corsParts : [];
tempCors = tempCors.concat(blockchainConfig.rpcCorsDomain.additionalCors || []);
blockchainConfig.rpcCorsDomain = tempCors.join(',');
}
if (blockchainConfig.wsOrigins === 'auto') {
blockchainConfig.wsOrigins = cors;
} else if (typeof blockchainConfig.wsOrigins === 'object') {
let tempCors = blockchainConfig.wsOrigins.auto ? corsParts : [];
tempCors = tempCors.concat(blockchainConfig.wsOrigins.additionalCors || []);
blockchainConfig.wsOrigins = tempCors.join(',');
}
}
_loadConfigFile(configFilePath, defaultConfig, enabledByDefault = false) {
if (!configFilePath) {
const configToReturn = defaultConfig.default || {};
configToReturn.enabled = enabledByDefault;
return configToReturn;
}
configFilePath = configFilePath.replace('.json', '').replace('.js', '');
let config;
if (fs.existsSync(configFilePath + '.js')) {
delete require.cache[configFilePath + '.js'];
config = require(configFilePath + '.js');
} else if (fs.existsSync(configFilePath + '.json')) {
config = fs.readJSONSync(configFilePath + '.json');
} else {
this.logger.warn(__("no config file found at %s using default config", configFilePath));
return defaultConfig.default || {};
}
return config;
}
_doMergeConfig(config, defaultConfig, env) {
const configObject = recursiveMerge(defaultConfig, config);
if (env) {
if (env === 'test' && !configObject[env]) {
// Disabled all configs in tests as they are opt in
return Object.assign({}, defaultConfig.default, {enabled: false});
}
return recursiveMerge(configObject.default || {}, configObject[env]);
} else if (env !== false) {
this.logger.info(__("No environment called %s found. Using defaults.", env));
}
return configObject;
}
_loadAndMergeConfig(configFilePath, defaultConfig, env, enabledByDefault = false) {
const config = this._loadConfigFile(configFilePath, defaultConfig, enabledByDefault);
return this._doMergeConfig(config, defaultConfig, env);
}
_getFileOrObject(object, filePath, property) {
if (typeof object === 'object') {
return object[property] ? dappPath(object[property]) : object[property];
}
return dappPath(object, filePath);
}
/*eslint complexity: ["error", 30]*/
loadBlockchainConfigFile() {
const blockchainDefaults = getBlockchainDefaults(this.env);
const configFilePath = this._getFileOrObject(this.configDir, 'blockchain', 'blockchain');
const userConfig = this._loadConfigFile(configFilePath, blockchainDefaults, true);
const envConfig = userConfig[this.env];
if (envConfig) {
if (envConfig.ethereumClientName || envConfig.hasOwnProperty('isDev') || envConfig.hasOwnProperty('mineWhenNeeded')) {
this.logger.error(__('The blockchain config has changed quite a bit in Embark 5\nPlease visit %s to know what has to be changed', embark5ChangesUrl.underline));
process.exit(1);
}
if (envConfig.clientConfig) {
Object.assign(envConfig, envConfig.clientConfig);
delete envConfig.clientConfig;
}
switch (envConfig.miningMode) {
case 'dev': envConfig.isDev = true; break;
case 'auto': envConfig.isDev = false; envConfig.mineWhenNeeded = true; break;
case 'always': envConfig.isDev = false; envConfig.mineWhenNeeded = false; envConfig.mine = true; break;
case 'off': envConfig.isDev = false; envConfig.mineWhenNeeded = false; envConfig.mine = false; break;
default: envConfig.isDev = false;
}
if (envConfig.cors) {
const autoIndex = envConfig.cors.indexOf('auto');
envConfig.rpcCorsDomain = {};
envConfig.wsOrigins = {};
if (autoIndex > -1) {
envConfig.rpcCorsDomain.auto = true;
envConfig.wsOrigins.auto = true;
envConfig.cors.splice(autoIndex, 1);
} else {
envConfig.rpcCorsDomain.auto = false;
envConfig.wsOrigins.auto = false;
}
envConfig.rpcCorsDomain.additionalCors = envConfig.cors;
envConfig.wsOrigins.additionalCors = envConfig.cors;
delete envConfig.cors;
}
userConfig[this.env] = envConfig;
}
this.blockchainConfig = this._doMergeConfig(userConfig, blockchainDefaults, this.env);
if (!configFilePath) {
this.blockchainConfig.default = true;
}
if (this.blockchainConfig.targetGasLimit && this.blockchainConfig.targetGasLimit.toString().match(unitRegex)) {
this.blockchainConfig.targetGasLimit = getWeiBalanceFromString(this.blockchainConfig.targetGasLimit, web3);
}
if (this.blockchainConfig.gasPrice && this.blockchainConfig.gasPrice.toString().match(unitRegex)) {
this.blockchainConfig.gasPrice = getWeiBalanceFromString(this.blockchainConfig.gasPrice, web3);
}
if (this.blockchainConfig.accounts) {
this.blockchainConfig.accounts.forEach(acc => {
if (acc.balance && acc.balance.toString().match(unitRegex)) {
acc.balance = getWeiBalanceFromString(acc.balance, web3);
}
});
}
if (!this.blockchainConfig.endpoint) {
const urlConfig = (this.blockchainConfig.wsHost) ? {
host: this.blockchainConfig.wsHost,
port: this.blockchainConfig.wsPort,
type: 'ws'
} : {
host: this.blockchainConfig.rpcHost,
port: this.blockchainConfig.rpcPort,
type: 'rpc'
};
this.blockchainConfig.endpoint = buildUrlFromConfig(urlConfig);
this.blockchainConfig.isAutoEndpoint = true;
}
if (
!this.shownNoAccountConfigMsg &&
(/rinkeby|testnet|livenet/).test(this.blockchainConfig.networkType) &&
!(this.blockchainConfig.accounts && this.blockchainConfig.accounts.find(acc => acc.password)) &&
!this.blockchainConfig.isDev &&
this.env !== 'development' && this.env !== 'test') {
this.logger.warn((
'\n=== ' + __('Cannot unlock account - account config missing').bold + ' ===\n' +
__('Geth is configured to sync to a testnet/livenet and needs to unlock an account ' +
'to allow your dApp to interact with geth, however, the address and password must ' +
'be specified in your blockchain config. Please update your blockchain config with ' +
'a valid address and password: \n') +
` - config/blockchain.js > ${this.env} > account\n\n`.italic +
__('Please also make sure the keystore file for the account is located at: ') +
'\n - Mac: ' + `~/Library/Ethereum/${this.env}/keystore`.italic +
'\n - Linux: ' + `~/.ethereum/${this.env}/keystore`.italic +
'\n - Windows: ' + `%APPDATA%\\Ethereum\\${this.env}\\keystore`.italic) +
__('\n\nAlternatively, you could change ' +
`config/blockchain.js > ${this.env} > networkType`.italic +
__(' to ') +
'"custom"\n'.italic).yellow
);
this.shownNoAccountConfigMsg = true;
}
const accountDocsMessage = __('For more info, check the docs: %s', 'https://embark.status.im/docs/blockchain_accounts_configuration.html'.underline);
if (this.blockchainConfig.account) {
this.logger.error(__('The `account` config for the blockchain was removed. Please use `accounts` instead.'));
this.logger.error(accountDocsMessage);
process.exit(1);
}
if (this.blockchainConfig.simulatorMnemonic) {
this.logger.error(__('The `simulatorMnemonic` config for the blockchain was removed. Please use `accounts` instead.'));
this.logger.error(accountDocsMessage);
process.exit(1);
}
this.events.emit('config:load:blockchain', this.blockchainConfig);
}
loadContractsConfigFile() {
let configObject = getContractDefaults(this.embarkConfig.versions);
const contractsConfigs = this.plugins.getPluginsProperty('contractsConfig', 'contractsConfigs');
contractsConfigs.forEach(function(pluginConfig) {
configObject = recursiveMerge(configObject, pluginConfig);
});
const configFilePath = this._getFileOrObject(this.configDir, 'contracts', 'contracts');
let newContractsConfig = this._loadAndMergeConfig(configFilePath, configObject, this.env);
if (newContractsConfig.contracts) {
this.logger.error(__('`contracts` has been renamed `deploy` in contracts config\nFor more information: %s', embark5ChangesUrl.underline));
process.exit(1);
}
if (newContractsConfig.deployment) {
this.logger.error(__('`deployment` has been removed from contracts config and is now part of blockchain config\nFor more information: %s', embark5ChangesUrl.underline));
process.exit(1);
}
if (newContractsConfig.gas.match(unitRegex)) {
newContractsConfig.gas = getWeiBalanceFromString(newContractsConfig.gas, web3);
}
newContractsConfig = prepareContractsConfig(newContractsConfig);
const afterDeploy = newContractsConfig.afterDeploy;
if (Array.isArray(afterDeploy)) {
newContractsConfig.afterDeploy = afterDeploy.map(replaceZeroAddressShorthand);
}
if (!deepEqual(newContractsConfig, this.contractsConfig)) {
this.contractsConfig = newContractsConfig;
}
this.events.emit('config:load:contracts', this.contractsConfig);
}
loadExternalContractsFiles() {
const contracts = this.contractsConfig.contracts;
const storageConfig = this.storageConfig;
if (storageConfig && storageConfig.upload && storageConfig.upload.getUrl) {
this.providerUrl = storageConfig.upload.getUrl;
}
for (const contractName in contracts) {
const contract = contracts[contractName];
if (!contract.file) {
continue;
}
let externalContractFile;
if (contract.file.startsWith('http') || contract.file.startsWith('git') || contract.file.startsWith('ipfs') || contract.file.startsWith('bzz')) {
const fileObj = getExternalContractUrl(contract.file, this.providerUrl);
if (!fileObj) {
return this.logger.error(__("HTTP contract file not found") + ": " + contract.file);
}
externalContractFile = new File({ path: fileObj.filePath, originalPath: fileObj.filePath, type: Types.http, basedir: '', externalUrl: fileObj.url, storageConfig });
} else if (fs.existsSync(contract.file)) {
externalContractFile = new File({ path: contract.file, originalPath: contract.file, type: Types.dappFile, basedir: '', storageConfig });
} else if (fs.existsSync(path.join('./node_modules/', contract.file))) {
const completePath = path.join('./node_modules/', contract.file);
externalContractFile = new File({ path: completePath, originalPath: completePath, type: Types.dappFile, basedir: '', storageConfig });
}
if (externalContractFile) {
const index = this.contractsFiles.findIndex(contractFile => contractFile.originalPath === externalContractFile.originalPath);
// It's important that we only add `externalContractFile` if it doesn't exist already
// within `contractsFiles`, otherwise we keep adding duplicates in subsequent
// compilation routines creating a memory leak.
if (index > -1) {
this.contractsFiles[index] = externalContractFile;
} else {
this.contractsFiles.push(externalContractFile);
}
} else {
this.logger.error(__("contract file not found") + ": " + contract.file);
}
}
}
loadStorageConfigFile() {
const versions = recursiveMerge({"ipfs-api": "17.2.4"}, this.embarkConfig.versions || {});
const configObject = {
default: {
versions,
enabled: true,
available_providers: ["ipfs", "swarm"],
ipfs_bin: "ipfs",
upload: {
provider: "ipfs",
protocol: "http",
host : defaultHost,
port: 5001,
getUrl: "http://localhost:8080/ipfs/"
},
dappConnection: [{provider: "ipfs", host: "localhost", port: 5001, getUrl: "http://localhost:8080/ipfs/"}]
}
};
const configFilePath = this._getFileOrObject(this.configDir, 'storage', 'storage');
this.storageConfig = this._loadAndMergeConfig(configFilePath, configObject, this.env);
this.events.emit('config:load:storage', this.storageConfig);
}
loadNameSystemConfigFile() {
// todo: spec out names for registration in the file itself for a dev chain
const configObject = {
default: {
enabled: false
}
};
const configFilePath = this._getFileOrObject(this.configDir, 'namesystem', 'namesystem');
this.namesystemConfig = this._loadAndMergeConfig(configFilePath, configObject, this.env);
}
loadCommunicationConfigFile() {
const configObject = {
default: {
enabled: true,
provider: "whisper",
available_providers: ["whisper"],
connection: {
host: defaultHost,
port: 8557,
type: "ws"
}
}
};
const configFilePath = this._getFileOrObject(this.configDir, 'communication', 'communication');
this.communicationConfig = this._loadAndMergeConfig(configFilePath, configObject, this.env);
this.events.emit('config:load:communication', this.communicationConfig);
}
loadWebServerConfigFile() {
const configObject = {
enabled: true,
host: defaultHost,
openBrowser: true,
port: 8000,
enableCatchAll: true,
protocol: "http"
};
const configFilePath = this._getFileOrObject(this.configDir, 'webserver', 'webserver');
const webServerConfig = this._loadAndMergeConfig(configFilePath, configObject, false);
if (webServerConfig.https) {
try {
webServerConfig.certOptions = {
key: fs.readFileSync(webServerConfig.key),
cert: fs.readFileSync(webServerConfig.cert)
};
webServerConfig.protocol = 'https';
} catch (e) {
this.logger.error(e.message);
this.logger.warn('Invalid path for key/cert in config/webserver.js. Using http instead.');
webServerConfig.certOptions = {};
webServerConfig.protocol = 'http';
}
}
if (configFilePath === false) {
this.webServerConfig = {enabled: false};
return;
}
if (this.webServerConfig) {
// cli flags to `embark run` should override configFile and defaults (configObject)
this.webServerConfig = recursiveMerge(webServerConfig, this.webServerConfig);
} else {
this.webServerConfig = webServerConfig;
}
if (!this.pipelineConfig.enabled) {
this.webServerConfig.enabled = false;
}
this.events.emit('config:load:webserver', this.webServerConfig);
}
loadEmbarkConfigFile() {
const configObject = {
options: {
solc: {
"optimize": true,
"optimize-runs": 200
}
},
generationDir: "embarkArtifacts"
};
this.embarkConfig = recursiveMerge(configObject, this.embarkConfig);
const contracts = this.embarkConfig.contracts;
// determine contract 'root' directories
this.contractDirectories = contracts.map((dir) => {
return dir.split("**")[0];
}).map((dir) => {
return dir.split("*.")[0];
});
this.contractDirectories.push(constants.httpContractsDirectory);
this.buildDir = this.embarkConfig.buildDir;
this.configDir = this.embarkConfig.config;
}
loadPipelineConfigFile() {
const defaultPipelineConfig = {
typescript: false,
enabled: true
};
let pipelineConfigPath = this._getFileOrObject(this.configDir, 'pipeline', 'pipeline');
// Embark applications in "simple" mode that aren't aware of `pipeline.js` configuration capabilities
// won't have a pipeline config path so we need to perform this safety check here, otherwise the
// next expression is going to throw.
if (pipelineConfigPath !== undefined) {
// At this point, `pipelineConfigPath` could be either `config/pipeline` or a filepath including its extension.
// We need to make sure that we always have an extension.
pipelineConfigPath = `${dappPath(pipelineConfigPath)}${path.extname(pipelineConfigPath) === '.js' ? '' : '.js'}`;
}
let pipelineConfig = defaultPipelineConfig;
if (pipelineConfigPath && fs.existsSync(pipelineConfigPath)) {
delete require.cache[pipelineConfigPath];
pipelineConfig = recursiveMerge(
recursiveMerge(true, pipelineConfig),
require(pipelineConfigPath)
);
}
this.pipelineConfig = pipelineConfig;
this.events.emit('config:load:pipeline', this.pipelineConfig);
}
loadAssetFiles() {
if (!this.embarkConfig.app) { return; }
Object.keys(this.embarkConfig.app).forEach(targetFile => {
this.assetFiles[targetFile] = this.loadFiles(this.embarkConfig.app[targetFile]);
});
}
loadFiles(files) {
const self = this;
const originalFiles = filesMatchingPattern(files);
const readFiles: File[] = [];
const storageConfig = self.storageConfig;
originalFiles.filter(function(file) {
return (file[0] === '$' || file.indexOf('.') >= 0);
}).filter(function(file) {
const basedir = findMatchingExpression(file, files);
readFiles.push(new File({path: file, originalPath: file, type: Types.dappFile, basedir, storageConfig}));
});
const filesFromPlugins: File[] = [];
const filePlugins = self.plugins.getPluginsFor('pipelineFiles');
filePlugins.forEach((plugin: Plugin) => {
try {
const fileObjects = plugin.runFilePipeline();
for (let i = 0; i < fileObjects.length; i++) {
const fileObject = fileObjects[i];
filesFromPlugins.push(fileObject);
}
} catch (err) {
self.logger.error(err.message);
}
});
filesFromPlugins.filter(function(file) {
if ((file.intendedPath && fileMatchesPattern(files, file.intendedPath)) || fileMatchesPattern(files, file.file)) {
readFiles.push(file);
}
});
return readFiles;
}
// NOTE: this doesn't work for internal modules
loadPluginContractFiles() {
const self = this;
const storageConfig = self.storageConfig;
const contractsPlugins = this.plugins.getPluginsFor('contractFiles');
contractsPlugins.forEach((plugin: Plugin) => {
plugin.contractsFiles.forEach(file => {
const filename = file.replace('./', '');
self.contractsFiles.push(new File({ path: filename, originalPath: path.join(plugin.pluginPath, filename), pluginPath: plugin.pluginPath, type: Types.custom, storageConfig,
resolver(callback) {
callback(plugin.loadPluginFile(file));
}
}));
});
});
}
}
function findMatchingExpression(filename, filesExpressions) {
for (const fileExpression of filesExpressions) {
const matchingFiles = filesMatchingPattern(fileExpression);
for (const matchFile of matchingFiles) {
if (matchFile === filename) {
return path.dirname(fileExpression).replace(/\*/g, '');
}
}
}
return path.dirname(filename);
}

View File

@ -39,23 +39,23 @@ export function getBlockchainDefaults(env) {
export function getContractDefaults(embarkConfigVersions) { export function getContractDefaults(embarkConfigVersions) {
const defaultVersions = { const defaultVersions = {
"web3": "1.2.1", web3: "1.2.1",
"solc": "0.5.0" solc: "0.5.0"
}; };
const versions = recursiveMerge(defaultVersions, embarkConfigVersions || {}); const versions = recursiveMerge(defaultVersions, embarkConfigVersions || {});
return { return {
"default": { default: {
"versions": versions, versions: versions,
"dappConnection": [ dappConnection: [
"$WEB3", "$WEB3",
"ws://localhost:8546", "ws://localhost:8546",
"localhost:8545" "localhost:8545"
], ],
"dappAutoEnable": true, dappAutoEnable: true,
"strategy": constants.deploymentStrategy.implicit, strategy: constants.deploymentStrategy.implicit,
"gas": "auto", gas: "auto",
"deploy": { deploy: {
} }
} }
}; };

View File

@ -1,11 +1,63 @@
import {ProcessManager, IPC} from 'embark-core'; import { Config } from './config';
import { Plugins } from './plugins';
import { EmbarkEmitter as Events } from './events';
import { ProcessManager } from './processes/processManager';
import { IPC } from './ipc';
import { ServicesMonitor } from './services_monitor';
import { normalizeInput } from 'embark-utils';
import { Logger } from 'embark-logger';
const EMBARK_PROCESS_NAME = 'embark'; const EMBARK_PROCESS_NAME = 'embark';
const utils = require('../utils/utils'); export class Engine {
const Logger = require('embark-logger');
env: string;
client: string;
locale: string;
embarkConfig: any;
interceptLogs: boolean;
version: string;
logFile: string;
logLevel: string;
events: Events;
context: any;
useDashboard: boolean;
webServerConfig: any;
webpackConfigName: string;
singleUseAuthToken: boolean;
ipcRole = 'client';
logger: Logger;
config: Config | undefined;
plugins: Plugins | undefined;
ipc: IPC | undefined;
processManager: ProcessManager | undefined;
servicesMonitor: ServicesMonitor | undefined;
package: any;
isDev: boolean | undefined;
class Engine {
constructor(options) { constructor(options) {
this.env = options.env; this.env = options.env;
this.client = options.client; this.client = options.client;
@ -21,24 +73,23 @@ class Engine {
this.webServerConfig = options.webServerConfig; this.webServerConfig = options.webServerConfig;
this.webpackConfigName = options.webpackConfigName; this.webpackConfigName = options.webpackConfigName;
this.singleUseAuthToken = options.singleUseAuthToken; this.singleUseAuthToken = options.singleUseAuthToken;
this.package = options.package;
this.ipcRole = options.ipcRole || 'client'; this.ipcRole = options.ipcRole || 'client';
} }
init(_options, callback) { init(_options, callback) {
callback = callback || function () {}; callback = callback || function() {};
const Events = require('./events.js');
const Config = require('./config.js');
let options = _options || {}; const options = _options || {};
this.events = options.events || this.events || new Events(); this.events = options.events || this.events || new Events();
this.logger = options.logger || new Logger({context: this.context, logLevel: options.logLevel || this.logLevel || 'info', events: this.events, logFile: this.logFile}); this.logger = options.logger || new Logger({context: this.context, logLevel: options.logLevel || this.logLevel || 'info', events: this.events, logFile: this.logFile});
this.config = new Config({env: this.env, logger: this.logger, events: this.events, context: this.context, webServerConfig: this.webServerConfig, version: this.version}); this.config = new Config({env: this.env, logger: this.logger, events: this.events, context: this.context, webServerConfig: this.webServerConfig, version: this.version, package: this.package});
this.config.loadConfigFiles({embarkConfig: this.embarkConfig, interceptLogs: this.interceptLogs}); this.config.loadConfigFiles({embarkConfig: this.embarkConfig, interceptLogs: this.interceptLogs});
this.plugins = this.config.plugins; this.plugins = this.config.plugins;
this.isDev = this.config && this.config.blockchainConfig && (this.config.blockchainConfig.isDev || this.config.blockchainConfig.default); this.isDev = this.config && this.config.blockchainConfig && (this.config.blockchainConfig.isDev || this.config.blockchainConfig.default);
if (this.interceptLogs || this.interceptLogs === undefined) { if (this.interceptLogs || this.interceptLogs === undefined) {
utils.interceptLogs(console, this.logger); interceptLogs(console, this.logger);
} }
this.ipc = new IPC({logger: this.logger, ipcRole: this.ipcRole}); this.ipc = new IPC({logger: this.logger, ipcRole: this.ipcRole});
@ -55,28 +106,36 @@ class Engine {
} }
startEngine(cb) { startEngine(cb) {
this.plugins.emitAndRunActionsForEvent("embark:engine:started", {}, (err) => { if (this.plugins) {
if (err) { this.plugins.emitAndRunActionsForEvent("embark:engine:started", {}, (err) => {
console.error("error starting engine"); if (err) {
console.error(err); console.error("error starting engine");
process.exit(1); console.error(err);
} process.exit(1);
}
cb();
});
} else {
cb(); cb();
}); }
} }
registerModule(moduleName, options) { registerModule(moduleName, options) {
this.plugins.loadInternalPlugin(moduleName, options || {}); if (this.plugins) {
this.plugins.loadInternalPlugin(moduleName, options || {});
}
} }
registerModulePackage(moduleName, options) { registerModulePackage(moduleName, options?: any) {
return this.plugins.loadInternalPlugin(moduleName, options || {}, true); if (this.plugins) {
return this.plugins.loadInternalPlugin(moduleName, options || {}, true);
}
} }
registerModuleGroup(groupName, _options) { registerModuleGroup(groupName, _options) {
let options = _options || {}; const options = _options || {};
let groups = { const groups = {
blockchain: this.blockchainComponents, blockchain: this.blockchainComponents,
coreComponents: this.coreComponents, coreComponents: this.coreComponents,
stackComponents: this.stackComponents, stackComponents: this.stackComponents,
@ -94,14 +153,14 @@ class Engine {
cockpit: this.cockpitModules cockpit: this.cockpitModules
}; };
let group = groups[groupName]; const group = groups[groupName];
if (!group) { if (!group) {
throw new Error("unknown service: " + groupName); throw new Error("unknown service: " + groupName);
} }
// need to be careful with circular references due to passing the web3 object // need to be careful with circular references due to passing the web3 object
//this.logger.trace("calling: " + serviceName + "(" + JSON.stringify(options) + ")"); // this.logger.trace("calling: " + serviceName + "(" + JSON.stringify(options) + ")");
return group.apply(this, [options]); return group.apply(this, [options]);
} }
@ -122,6 +181,7 @@ class Engine {
} }
coreComponents() { coreComponents() {
// TODO: should be made into a component // TODO: should be made into a component
this.processManager = new ProcessManager({ this.processManager = new ProcessManager({
events: this.events, events: this.events,
@ -129,17 +189,22 @@ class Engine {
plugins: this.plugins plugins: this.plugins
}); });
const ServicesMonitor = require('./services_monitor.js');
this.servicesMonitor = new ServicesMonitor({events: this.events, logger: this.logger, plugins: this.plugins}); this.servicesMonitor = new ServicesMonitor({events: this.events, logger: this.logger, plugins: this.plugins});
this.servicesMonitor.addCheck('Embark', (cb) => {
return cb({name: 'Embark ' + this.version, status: 'on'});
}, 0);
let plugin = this.plugins.createPlugin('coreservicesplugin', {}); if (this.servicesMonitor) {
plugin.registerActionForEvent("embark:engine:started", (_params, cb) => { this.servicesMonitor.addCheck('Embark', (cb) => {
this.servicesMonitor.startMonitor(); return cb({name: 'Embark ' + this.version, status: 'on'});
cb(); }, 0);
});
if (this.plugins) {
const plugin = this.plugins.createPlugin('coreservicesplugin', {});
plugin.registerActionForEvent("embark:engine:started", (_params, cb) => {
this.servicesMonitor && this.servicesMonitor.startMonitor();
cb();
});
}
}
this.registerModulePackage('embark-code-runner', {ipc: this.ipc}); this.registerModulePackage('embark-code-runner', {ipc: this.ipc});
// TODO: we shouldn't need useDashboard // TODO: we shouldn't need useDashboard
@ -236,14 +301,35 @@ class Engine {
this.registerModulePackage('embark-ens'); this.registerModulePackage('embark-ens');
} }
cockpitModules() { cockpitModules() {
this.registerModulePackage('embark-authenticator', {singleUseAuthToken: this.singleUseAuthToken}); this.registerModulePackage('embark-authenticator', {singleUseAuthToken: this.singleUseAuthToken});
this.registerModulePackage('embark-api', {plugins: this.plugins}); this.registerModulePackage('embark-api', {plugins: this.plugins});
// Register logs for the cockpit console // Register logs for the cockpit console
this.events.request('process:logs:register', {processName: EMBARK_PROCESS_NAME, eventName: "log", silent: false, alwaysAlreadyLogged: true}); this.events.request('process:logs:register', {processName: EMBARK_PROCESS_NAME, eventName: "log", silent: false, alwaysAlreadyLogged: true});
} }
} }
module.exports = Engine; function interceptLogs(consoleContext, logger) {
const context: any = {};
context.console = consoleContext;
context.console.log = function() {
logger.info(normalizeInput(arguments));
};
context.console.warn = function() {
logger.warn(normalizeInput(arguments));
};
context.console.info = function() {
logger.info(normalizeInput(arguments));
};
context.console.debug = function() {
// TODO: ue JSON.stringify
logger.debug(normalizeInput(arguments));
};
context.console.trace = function() {
logger.trace(normalizeInput(arguments));
};
context.console.dir = function() {
logger.dir(normalizeInput(arguments));
};
}

View File

@ -1,5 +1,5 @@
import { __ } from 'embark-i18n'; import { __ } from 'embark-i18n';
var EventEmitter = require('events'); const EventEmitter = require('events');
const cloneDeep = require('lodash.clonedeep'); const cloneDeep = require('lodash.clonedeep');
const fs = require('fs-extra'); const fs = require('fs-extra');
@ -8,22 +8,26 @@ function debugEventsEnabled() {
return process && process.env && process.env.DEBUGEVENTS; return process && process.env && process.env.DEBUGEVENTS;
} }
function warnIfLegacy(eventName) { function warnIfLegacy(eventName: string) {
const legacyEvents = []; const legacyEvents: string[] = [];
if (legacyEvents.indexOf(eventName) >= 0) { if (legacyEvents.indexOf(eventName) >= 0) {
console.info(__("this event is deprecated and will be removed in future versions %s", eventName)); console.info(__("this event is deprecated and will be removed in future versions %s", eventName));
} }
} }
function getOrigin() { function getOrigin() {
if (!(debugEventsEnabled())) return ""; if (!(debugEventsEnabled())) { return ""; }
let origin = ((new Error().stack).split("at ")[3]).trim(); const stack = new Error().stack;
origin = origin.split("(")[0].trim(); if (stack) {
return origin; let origin = stack.split("at ")[3].trim();
origin = origin.split("(")[0].trim();
return origin;
}
return '';
} }
function log(eventType, eventName, origin) { function log(eventType, eventName, origin?: string) {
if (!(debugEventsEnabled())) return; if (!(debugEventsEnabled())) { return; }
if (['end', 'prefinish', 'error', 'new', 'demo', 'block', 'version'].indexOf(eventName) >= 0) { if (['end', 'prefinish', 'error', 'new', 'demo', 'block', 'version'].indexOf(eventName) >= 0) {
return; return;
} }
@ -32,8 +36,11 @@ function log(eventType, eventName, origin) {
} }
// fs.appendFileSync(".embark/events.log", (new Error().stack) + "\n"); // fs.appendFileSync(".embark/events.log", (new Error().stack) + "\n");
if (!origin && origin !== "") { if (!origin && origin !== "") {
origin = ((new Error().stack).split("at ")[3]).trim(); const stack = new Error().stack;
origin = origin.split("(")[0].trim(); if (stack) {
origin = stack.split("at ")[3].trim();
origin = origin.split("(")[0].trim();
}
// origin = getOrigin(); // origin = getOrigin();
} }
@ -50,7 +57,7 @@ function log(eventType, eventName, origin) {
// cmdNames[cmdName] = origin; // cmdNames[cmdName] = origin;
// } // }
class EmbarkEmitter extends EventEmitter { export class EmbarkEmitter extends EventEmitter {
emit(requestName, ...args) { emit(requestName, ...args) {
warnIfLegacy(arguments[0]); warnIfLegacy(arguments[0]);
@ -59,7 +66,6 @@ class EmbarkEmitter extends EventEmitter {
} }
} }
// EmbarkEmitter.prototype.log = log; // EmbarkEmitter.prototype.log = log;
EmbarkEmitter.prototype.log = log; EmbarkEmitter.prototype.log = log;
@ -98,8 +104,8 @@ EmbarkEmitter.prototype.setHandler = function(requestName, cb) {
}; };
EmbarkEmitter.prototype.request2 = function() { EmbarkEmitter.prototype.request2 = function() {
let requestName = arguments[0]; const requestName = arguments[0];
let other_args = [].slice.call(arguments, 1); const other_args: any[] = [].slice.call(arguments, 1);
log("\nREQUEST", requestName); log("\nREQUEST", requestName);
warnIfLegacy(requestName); warnIfLegacy(requestName);
@ -112,10 +118,10 @@ EmbarkEmitter.prototype.request2 = function() {
} }
} }
let promise = new Promise((resolve, reject) => { const promise = new Promise((resolve, reject) => {
other_args.push( other_args.push(
(err, ...res) => { (err, ...res) => {
if (err) return reject(err); if (err) { return reject(err); }
if (res.length && res.length > 1) { if (res.length && res.length > 1) {
return resolve(res); return resolve(res);
} }
@ -126,7 +132,7 @@ EmbarkEmitter.prototype.request2 = function() {
this._emit('request:' + requestName, ...other_args); this._emit('request:' + requestName, ...other_args);
}); });
let ogStack = (new Error().stack); const ogStack = (new Error().stack);
promise.catch((e) => { promise.catch((e) => {
if (debugEventsEnabled()) { if (debugEventsEnabled()) {
@ -141,8 +147,8 @@ EmbarkEmitter.prototype.request2 = function() {
}; };
EmbarkEmitter.prototype.request = function() { EmbarkEmitter.prototype.request = function() {
let requestName = arguments[0]; const requestName = arguments[0];
let other_args = [].slice.call(arguments, 1); const other_args = [].slice.call(arguments, 1);
log("\nREQUEST(OLD)", requestName); log("\nREQUEST(OLD)", requestName);
warnIfLegacy(requestName); warnIfLegacy(requestName);
@ -160,7 +166,7 @@ EmbarkEmitter.prototype.request = function() {
// if we don't have a command handler set for this event yet, // if we don't have a command handler set for this event yet,
// store it and fire it once a command handler is set // store it and fire it once a command handler is set
if (!this.listeners(listenerName).length) { if (!this.listeners(listenerName).length) {
if(!toFire[listenerName]) { if (!toFire[listenerName]) {
toFire[listenerName] = []; toFire[listenerName] = [];
} }
toFire[listenerName].push(other_args); toFire[listenerName].push(other_args);
@ -177,9 +183,9 @@ EmbarkEmitter.prototype.setCommandHandler = function(requestName, cb) {
// let origin = ((new Error().stack).split("at ")[3]).trim(); // let origin = ((new Error().stack).split("at ")[3]).trim();
// origin = origin.split("(")[0].trim(); // origin = origin.split("(")[0].trim();
let origin = getOrigin(); const origin = getOrigin();
let listener = function(_cb) { const listener = function(_cb) {
log("== REQUEST RESPONSE", requestName, origin); log("== REQUEST RESPONSE", requestName, origin);
cb.call(this, ...arguments); cb.call(this, ...arguments);
}; };
@ -232,5 +238,3 @@ EmbarkEmitter.prototype.setCommandHandlerOnce = function(requestName, cb) {
cb.call(this, ...arguments); cb.call(this, ...arguments);
}); });
}; };
module.exports = EmbarkEmitter;

View File

@ -0,0 +1,93 @@
/* global module process require */
/* tslint:disable */
import { joinPath } from 'embark-utils';
import * as fs from 'fs-extra';
import parseJson from 'parse-json';
import * as path from 'path';
import 'colors';
export function mkdirpSync(args: any) { return fs.mkdirpSync(args); }
export function mkdirp(args: any, args2?: any) { return fs.mkdirp(args, args2); }
export function readdir(args: any, args2?: any) { return fs.readdir(args, args2); }
export function stat(args: any, args2?: any) { return fs.stat(args, args2); }
export function remove(args: any, args2: any) { return fs.remove(args, args2); }
export function copy(args: any, args2?: any, args3?: any, args4?: any) { return fs.copy(args, args2, args3, args4); }
export function copySync(args: any, args2?: any, args3?: any) { return fs.copySync(args, args2, args3); }
export function move(args: any, args2?: any, args3?: any, args4?: any) { return fs.move(args, args2, args3, args4); }
export function moveSync(args: any, args2?: any, args3?: any) { return fs.moveSync(args, args2, args3); }
export function symlink(args: any, args2?: any, args3?: any, args4?: any) { return fs.symlink(args, args2, args3, args4); }
export function appendFileSync(args: any, args2: any, args3?: any) { return fs.appendFileSync(args, args2, args3); }
export function writeFile(args: any, args2: any, args3?: any, args4?: any) { return fs.writeFile(args, args2, args3, args4); }
export function writeFileSync(args: any, args2: any, args3?: any) { return fs.writeFileSync(args, args2, args3); }
export function readFile(args: any, args2?: any, args3?: any) { return fs.readFile(args, args2, args3); }
export function readFileSync(args: any, args2?: any) { return fs.readFileSync(args, args2); }
export function readdirSync(args: any, args2?: any) { return fs.readdirSync(args, args2); }
export function statSync(args: any, args2?: any) { return fs.statSync(args, args2); }
export function readJSONSync(args: any, args2?: any) {
let json;
try {
json = parseJson(readFileSync(args, args2));
} catch (e) {
console.error('error: '.red + args.green.underline + ' ' + e.message.green);
process.exit(1);
}
return json;
}
export function writeJSONSync(args: any, args2: any, args3?: any) { return fs.writeJSONSync(args, args2, args3); }
export function outputJSONSync(args: any, args2: any, args3?: any) { return fs.outputJSONSync(args, args2, args3); }
export function writeJson(args: any, args2: any, args3?: any, args4?: any) { return fs.writeJson(args, args2, args3, args4); }
export function existsSync(args: any) { return fs.existsSync(args); }
export function ensureFileSync(args: any) { return fs.ensureFileSync(args); }
export function ensureDirSync(args: any, args2?: any) { return fs.ensureDirSync(args, args2); }
export function access(args: any, args2?: any, args3?: any) { return fs.access(args, args2, args3); }
export function removeSync(args: any) { return fs.removeSync(args); }
export function createWriteStream(args: any, args2?: any) { return fs.createWriteStream(args, args2); }
export function copyPreserve(sourceFilePath, targetFilePath) {
const implementation = (sourceFilePath, targetFilePath) => {
let ext = 1;
let preserved = targetFilePath;
while (fs.existsSync(preserved)) {
const extname = path.extname(targetFilePath);
preserved = joinPath(
path.dirname(targetFilePath),
`${path.basename(targetFilePath, extname)}.${ext}${extname}`
);
ext++;
}
if (preserved !== targetFilePath) {
fs.copySync(targetFilePath, preserved);
}
fs.copySync(sourceFilePath, targetFilePath);
};
return implementation(sourceFilePath, targetFilePath);
}
export function outputFileSync(args: any, args2: any, args3?: any) { return fs.outputFileSync(args, args2, args3); }

View File

@ -1,5 +0,0 @@
export { ProcessLauncher } from './processes/processLauncher';
export { ProcessManager } from './processes/processManager';
export { ProcessWrapper } from './processes/processWrapper';
export { IPC } from './ipc';

View File

@ -0,0 +1,14 @@
export { ProcessLauncher } from './processes/processLauncher';
export { ProcessWrapper } from './processes/processWrapper';
export { Config } from './config';
export { IPC } from './ipc';
export { Engine } from './engine';
import { EmbarkEmitter as Events } from './events';
export { Events };
export { Plugins } from './plugins';
export { TestLogger } from './utils/test_logger';
export { TemplateGenerator } from './utils/template_generator';
import * as fs from './fs';
export { fs };

View File

@ -0,0 +1,363 @@
import { fileMatchesPattern } from './utils/utils';
import { __ } from 'embark-i18n';
import { dappPath, embarkPath, isEs6Module, joinPath } from 'embark-utils';
import { Logger } from 'embark-logger';
const constants = require('embark-core/constants');
const fs = require('fs-extra');
const deepEqual = require('deep-equal');
// TODO: pass other params like blockchainConfig, contract files, etc..
export class Plugin {
dappPath = dappPath;
embarkPath = embarkPath;
name: string;
isInternal: boolean;
pluginModule: any;
pluginPath: string;
pluginConfig: any;
shouldInterceptLogs: boolean;
clientWeb3Providers: any[] = [];
beforeDeploy: any[] = [];
contractsGenerators: any[] = [];
generateCustomContractCode = null;
testContractFactory = null;
pipeline: any[] = [];
pipelineFiles: any[] = [];
console: any[] = [];
contractsConfigs: any[] = [];
contractsFiles: any[] = [];
compilers: any[] = [];
serviceChecks: any[] = [];
dappGenerators: any[] = [];
pluginTypes: string[] = [];
uploadCmds: any[] = [];
apiCalls: any[] = [];
imports: any[] = [];
embarkjs_code: any[] = [];
generated_code: any[] = [];
embarkjs_init_code: any[] = [];
embarkjs_init_console_code: any[] = [];
fs: any;
afterContractsDeployActions: any[] = [];
onDeployActions: any[] = [];
eventActions: any = {};
_loggerObject: Logger;
events: any;
config: any;
plugins: any;
env: any;
loaded = false;
currentContext: any;
acceptedContext: any;
version: string;
constants: any;
logger: Logger;
constructor(options) {
this.name = options.name;
this.isInternal = options.isInternal;
this.pluginModule = options.pluginModule;
this.pluginPath = options.pluginPath;
this.pluginConfig = options.pluginConfig;
this.shouldInterceptLogs = options.interceptLogs;
this.fs = fs;
this._loggerObject = options.logger;
this.logger = this._loggerObject; // Might get changed if we do intercept
this.events = options.events;
this.config = options.config;
this.plugins = options.plugins;
this.env = options.env;
this.currentContext = options.context;
this.acceptedContext = options.pluginConfig.context || [constants.contexts.any];
this.version = options.version;
this.constants = constants;
if (!Array.isArray(this.currentContext)) {
this.currentContext = [this.currentContext];
}
if (!Array.isArray(this.acceptedContext)) {
this.acceptedContext = [this.acceptedContext];
}
}
_log(type) {
this._loggerObject[type](this.name + ':', ...[].slice.call(arguments, 1));
}
setUpLogger() {
this.logger = {
log: this._log.bind(this, 'log'),
warn: this._log.bind(this, 'warn'),
error: this._log.bind(this, 'error'),
info: this._log.bind(this, 'info'),
debug: this._log.bind(this, 'debug'),
trace: this._log.bind(this, 'trace'),
dir: this._log.bind(this, 'dir')
};
}
isContextValid() {
if (this.currentContext.includes(constants.contexts.any) || this.acceptedContext.includes(constants.contexts.any)) {
return true;
}
return this.acceptedContext.some(context => {
return this.currentContext.includes(context);
});
}
hasContext(context) {
return this.currentContext.includes(context);
}
loadPlugin() {
if (!this.isContextValid()) {
this.logger.warn(__('Plugin {{name}} can only be loaded in the context of "{{contexts}}"', {name: this.name, contexts: this.acceptedContext.join(', ')}));
return false;
}
this.loaded = true;
if (this.shouldInterceptLogs) {
this.setUpLogger();
}
if (isEs6Module(this.pluginModule)) {
if (this.pluginModule.default) {
this.pluginModule = this.pluginModule.default;
}
return new this.pluginModule(this);
}
this.pluginModule.call(this, this);
}
loadInternalPlugin() {
if (isEs6Module(this.pluginModule)) {
if (this.pluginModule.default) {
this.pluginModule = this.pluginModule.default;
}
}
return new this.pluginModule(this, this.pluginConfig); /*eslint no-new: "off"*/
}
loadPluginFile(filename) {
return fs.readFileSync(this.pathToFile(filename)).toString();
}
pathToFile(filename) {
if (!this.pluginPath) {
throw new Error('pluginPath not defined for plugin: ' + this.name);
}
return joinPath(this.pluginPath, filename);
}
// TODO: add deploy provider
registerClientWeb3Provider(cb) {
this.clientWeb3Providers.push(cb);
this.addPluginType('clientWeb3Provider');
}
registerContractsGeneration(cb) {
this.contractsGenerators.push(cb);
this.addPluginType('contractGeneration');
}
registerCustomContractGenerator(cb) {
this.generateCustomContractCode = cb;
this.addPluginType('customContractGeneration');
}
registerTestContractFactory(cb) {
this.testContractFactory = cb;
this.addPluginType('testContractFactory');
}
registerPipeline(matcthingFiles, cb) {
// TODO: generate error for more than one pipeline per plugin
this.pipeline.push({matcthingFiles, cb});
this.addPluginType('pipeline');
}
registerDappGenerator(framework, cb) {
this.dappGenerators.push({framework, cb});
this.pluginTypes.push('dappGenerator');
}
registerCustomType(type) {
this.pluginTypes.push(type);
}
addFileToPipeline(file, intendedPath, options) {
this.pipelineFiles.push({file, intendedPath, options});
this.addPluginType('pipelineFiles');
}
addContractFile(file) {
if (this.isInternal) {
throw new Error("this API cannot work for internal modules. please use an event command instead: config:contractsFiles:add");
}
this.contractsFiles.push(file);
this.addPluginType('contractFiles');
}
registerConsoleCommand(optionsOrCb) {
if (typeof optionsOrCb === 'function') {
this.logger.warn(__('Registering console commands with function syntax is deprecated and will likely be removed in future versions of Embark'));
this.logger.info(__('You can find the new API documentation here: %s', 'https://embark.status.im/docs/plugin_reference.html#registerConsoleCommand-options'.underline));
}
this.console.push(optionsOrCb);
this.addPluginType('console');
}
// TODO: this only works for services done on startup
registerServiceCheck(checkName, checkFn, time) {
this.serviceChecks.push({checkName, checkFn, time});
this.addPluginType('serviceChecks');
}
has(pluginType) {
return this.pluginTypes.indexOf(pluginType) >= 0;
}
addPluginType(pluginType) {
this.pluginTypes.push(pluginType);
this.pluginTypes = Array.from(new Set(this.pluginTypes));
}
generateProvider(args) {
return this.clientWeb3Providers.map(function(cb) {
return cb.call(this, args);
}).join("\n");
}
generateContracts(args) {
return this.contractsGenerators.map(function(cb) {
return cb.call(this, args);
}).join("\n");
}
registerContractConfiguration(config) {
this.contractsConfigs.push(config);
this.addPluginType('contractsConfig');
}
registerCompiler(extension, cb) {
this.compilers.push({extension, cb});
this.addPluginType('compilers');
}
registerUploadCommand(cmd, cb) {
this.uploadCmds.push({cmd, cb});
this.addPluginType('uploadCmds');
}
addCodeToEmbarkJS(code) {
this.addPluginType('embarkjsCode');
// TODO: what is this/why
if (!this.embarkjs_code.some((existingCode) => deepEqual(existingCode, code))) {
this.embarkjs_code.push(code);
}
}
addGeneratedCode(codeCb) {
this.addPluginType('generatedCode');
this.generated_code.push(codeCb);
}
addProviderInit(providerType, code, initCondition) {
this.embarkjs_init_code[providerType] = this.embarkjs_init_code[providerType] || [];
this.embarkjs_init_code[providerType].push([code, initCondition]);
this.addPluginType('initCode');
}
addConsoleProviderInit(providerType, code, initCondition) {
this.embarkjs_init_console_code[providerType] = this.embarkjs_init_console_code[providerType] || [];
this.addPluginType('initConsoleCode');
const toAdd = [code, initCondition];
if (!this.embarkjs_init_console_code[providerType].some((initConsoleCode) => deepEqual(initConsoleCode, toAdd))) {
this.embarkjs_init_console_code[providerType].push(toAdd);
}
}
registerImportFile(importName, importLocation) {
this.imports.push([importName, importLocation]);
this.addPluginType('imports');
}
registerActionForEvent(eventName, cb) {
if (!this.eventActions[eventName]) {
this.eventActions[eventName] = [];
}
this.eventActions[eventName].push(cb);
this.addPluginType('eventActions');
}
registerAPICall(method, endpoint, cb) {
this.apiCalls.push({method, endpoint, cb});
this.addPluginType('apiCalls');
this.events.emit('plugins:register:api', {method, endpoint, cb});
}
runFilePipeline() {
return this.pipelineFiles.map(file => {
let obj: any = {};
obj.filename = file.file.replace('./', '');
obj.content = this.loadPluginFile(file.file).toString();
obj.intendedPath = file.intendedPath;
obj.options = file.options;
obj.path = this.pathToFile(obj.filename);
return obj;
});
}
runPipeline(args) {
// TODO: should iterate the pipelines
let pipeline = this.pipeline[0];
let shouldRunPipeline = fileMatchesPattern(pipeline.matcthingFiles, args.targetFile);
if (shouldRunPipeline) {
return pipeline.cb.call(this, args);
}
return args.source;
}
}

View File

@ -0,0 +1,272 @@
import * as fs from './fs';
import { Plugin } from './plugin';
import { EmbarkEmitter as Events } from './events';
import { Config } from './config';
import * as async from 'async';
import { dappPath, embarkPath } from 'embark-utils';
import { Logger } from 'embark-logger';
export class Plugins {
pluginList = [];
interceptLogs: boolean;
plugins: Plugin[] = [];
logger: Logger;
events: Events;
config: Config;
context: any;
fs: any;
env: string;
version: string;
static deprecated = {
'embarkjs-connector-web3': '4.1.0'
};
constructor(options) {
this.pluginList = options.plugins || [];
this.interceptLogs = options.interceptLogs;
// TODO: need backup 'NullLogger'
this.logger = options.logger;
this.events = options.events;
this.config = options.config;
this.context = options.context;
this.fs = fs;
this.env = options.env;
this.version = options.version;
}
loadPlugins() {
Object.entries(Plugins.deprecated).forEach(([pluginName, embarkVersion]) => {
if (this.pluginList[pluginName]) {
delete this.pluginList[pluginName];
this.logger.warn(`${pluginName} plugin was not loaded because it has been deprecated as of embark v${embarkVersion}, please remove it from this project's embark.json and package.json`);
}
});
Object.entries(this.pluginList).forEach(([pluginName, pluginConfig]) => {
this.loadPlugin(pluginName, pluginConfig);
});
}
listPlugins() {
return this.plugins.reduce((list: string[], plugin) => {
if (plugin.loaded) {
list.push(plugin.name);
}
return list;
}, []);
}
// for services that act as a plugin but have core functionality
createPlugin(pluginName, pluginConfig) {
const plugin = {};
const pluginPath = false;
const pluginWrapper = new Plugin({
name: pluginName,
pluginModule: plugin,
pluginConfig,
logger: this.logger,
pluginPath,
interceptLogs: this.interceptLogs,
events: this.events,
config: this.config,
plugins: this.plugins,
fs: this.fs,
isInternal: true,
context: this.context
});
this.plugins.push(pluginWrapper);
return pluginWrapper;
}
loadInternalPlugin(pluginName, pluginConfig, isPackage?: boolean) {
let pluginPath, plugin;
if (isPackage) {
pluginPath = pluginName;
plugin = require(pluginName);
} else {
pluginPath = embarkPath('dist/lib/modules/' + pluginName);
plugin = require(pluginPath);
}
if (plugin.default) {
plugin = plugin.default;
}
const pluginWrapper = new Plugin({
name: pluginName,
pluginModule: plugin,
pluginConfig: pluginConfig || {},
logger: this.logger,
pluginPath,
interceptLogs: this.interceptLogs,
events: this.events,
config: this.config,
plugins: this.plugins,
fs: this.fs,
isInternal: true,
context: this.context,
env: this.env
});
const pluginInstance = pluginWrapper.loadInternalPlugin();
this.plugins.push(pluginWrapper);
return pluginInstance;
}
loadPlugin(pluginName, pluginConfig) {
const pluginPath = dappPath('node_modules', pluginName);
let plugin = require(pluginPath);
if (plugin.default) {
plugin = plugin.default;
}
const pluginWrapper = new Plugin({
name: pluginName,
pluginModule: plugin,
pluginConfig,
logger: this.logger,
pluginPath,
interceptLogs: this.interceptLogs,
events: this.events,
config: this.config,
plugins: this.plugins,
fs: this.fs,
isInternal: false,
context: this.context,
version: this.version
});
pluginWrapper.loadPlugin();
this.plugins.push(pluginWrapper);
}
getPluginsFor(pluginType) {
return this.plugins.filter(function(plugin) {
return plugin.has(pluginType);
});
}
getPluginsProperty(pluginType, property, sub_property?: any) {
const matchingPlugins = this.plugins.filter(function(plugin) {
return plugin.has(pluginType);
});
// Sort internal plugins first
matchingPlugins.sort((a, b) => {
if (a.isInternal) {
return -1;
}
if (b.isInternal) {
return 1;
}
return 0;
});
let matchingProperties = matchingPlugins.map((plugin) => {
if (sub_property) {
return plugin[property][sub_property];
}
return plugin[property];
});
// Remove empty properties
matchingProperties = matchingProperties.filter((property) => property);
// return flattened list
if (matchingProperties.length === 0) { return []; }
return matchingProperties.reduce((a, b) => a.concat(b)) || [];
}
getPluginsPropertyAndPluginName(pluginType, property, sub_property) {
const matchingPlugins = this.plugins.filter(function(plugin) {
return plugin.has(pluginType);
});
// Sort internal plugins first
matchingPlugins.sort((a, b) => {
if (a.isInternal) {
return -1;
}
if (b.isInternal) {
return 1;
}
return 0;
});
let matchingProperties: any[] = [];
matchingPlugins.map((plugin) => {
if (sub_property) {
const newList = [];
for (const kall of (plugin[property][sub_property] || [])) {
matchingProperties.push([kall, plugin.name]);
}
return newList;
}
const newList = [];
for (const kall of (plugin[property] || [])) {
matchingProperties.push([kall, plugin.name]);
}
return newList;
});
// Remove empty properties
matchingProperties = matchingProperties.filter((property) => property[0]);
// return flattened list
if (matchingProperties.length === 0) { return []; }
// return matchingProperties.reduce((a,b) => { return a.concat(b); }) || [];
return matchingProperties;
}
// TODO: because this is potentially hanging, we should issue a trace warning if the event does not exists
runActionsForEvent(eventName, args, cb) {
const self = this;
if (typeof (args) === 'function') {
cb = args;
args = [];
}
const actionPlugins = this.getPluginsPropertyAndPluginName('eventActions', 'eventActions', eventName);
if (actionPlugins.length === 0) {
return cb(null, args);
}
this.events.log("ACTION", eventName, "");
async.reduce(actionPlugins, args, function(current_args, pluginObj: any, nextEach) {
const [plugin, pluginName] = pluginObj;
self.events.log("== ACTION FOR " + eventName, plugin.name, pluginName);
if (typeof (args) === 'function') {
plugin.call(plugin, (...params) => {
nextEach(...params || current_args);
});
} else {
plugin.call(plugin, args, (...params) => {
nextEach(...params || current_args);
});
}
}, cb);
}
emitAndRunActionsForEvent(eventName, args, cb) {
if (typeof (args) === 'function') {
cb = args;
args = [];
}
this.events.emit(eventName, args);
return this.runActionsForEvent(eventName, args, cb);
}
}

View File

@ -0,0 +1,103 @@
import { EmbarkEmitter as Events } from './events';
import { Plugins } from './plugins';
import { __ } from 'embark-i18n';
import { Logger } from 'embark-logger';
export class ServicesMonitor {
events: Events;
logger: Logger;
plugins: Plugins;
checkList: any = {};
checkTimers: any = {};
checkState: any = {};
working = false;
constructor(options) {
this.events = options.events;
this.logger = options.logger;
this.plugins = options.plugins;
this.events.setCommandHandler("services:register", (checkName, checkFn, time, initialStatus) => {
this.addCheck(checkName, checkFn, time, initialStatus);
});
}
initCheck(checkName) {
const self = this;
const check = this.checkList[checkName];
if (!check) {
return false;
}
self.events.on('check:' + checkName, function(obj) {
if (check && check.status === 'off' && obj.status === 'on') {
self.events.emit('check:backOnline:' + checkName);
}
if (check && check.status === 'on' && obj.status === 'off') {
self.events.emit('check:wentOffline:' + checkName);
}
check.status = obj.status;
// const newState = {name: obj.name, status: obj.status, serviceName: checkName};
// if (!deepEqual(newState, self.checkState[checkName])) {
self.checkState[checkName] = {name: obj.name, status: obj.status, serviceName: checkName};
self.events.emit("servicesState", self.checkState);
// }
});
if (check.interval !== 0) {
self.checkTimers[checkName] = setInterval(function() {
check.fn.call(check.fn, function(obj) {
self.events.emit('check:' + checkName, obj);
});
}, check.interval);
}
check.fn.call(check.fn, function(obj) {
self.events.emit('check:' + checkName, obj);
});
}
addCheck(checkName, checkFn, time, initialState?: any) {
this.logger.trace('add check: ' + checkName);
this.checkList[checkName] = {fn: checkFn, interval: time || 5000, status: initialState};
if (this.working) {
this.initCheck(checkName);
}
}
stopCheck(name) {
clearInterval(this.checkTimers[name]);
delete this.checkTimers[name];
delete this.checkList[name];
delete this.checkState[name];
}
startMonitor() {
const self = this;
this.working = true;
this.logger.trace('startMonitor');
const servicePlugins = this.plugins.getPluginsProperty('serviceChecks', 'serviceChecks');
servicePlugins.forEach(function(pluginCheck) {
self.addCheck(pluginCheck.checkName, pluginCheck.checkFn, pluginCheck.time);
});
Object.keys(this.checkList).forEach(checkName => {
try {
self.initCheck(checkName);
} catch (err) {
self.logger.error(__("error running service check"));
self.logger.error(err.message);
}
});
}
}

View File

@ -1,7 +1,12 @@
import { __ } from 'embark-i18n'; import { __ } from 'embark-i18n';
const fs = require('../core/fs.js');
import decompress from 'decompress';
import * as path from 'path';
import shelljs from 'shelljs';
import * as fs from '../fs';
const hostedGitInfo = require('hosted-git-info'); const hostedGitInfo = require('hosted-git-info');
const utils = require('./utils.js'); import { filesMatchingPattern } from './utils';
import { import {
embarkPath, embarkPath,
downloadFile, downloadFile,
@ -27,7 +32,7 @@ const REPLACEMENTS = {
'gitlab.com/': 'gitlab:' 'gitlab.com/': 'gitlab:'
}; };
class TemplateGenerator { export class TemplateGenerator {
constructor(templateName) { constructor(templateName) {
this.isInsideMonorepo = isInsideMonorepoSync(); this.isInsideMonorepo = isInsideMonorepoSync();
if (this.isInsideMonorepo) { if (this.isInsideMonorepo) {
@ -46,7 +51,7 @@ class TemplateGenerator {
async download(url, tmpFilePath, browse) { async download(url, tmpFilePath, browse) {
console.log(__('Installing template from ' + browse).green); console.log(__('Installing template from ' + browse).green);
console.log(__('Downloading template...').green); console.log(__('Downloading template...').green);
fs.mkdirpSync(utils.dirname(tmpFilePath)); fs.mkdirpSync(path.dirname(tmpFilePath));
try { try {
await promisify(downloadFile)(url, tmpFilePath); await promisify(downloadFile)(url, tmpFilePath);
} catch (e) { } catch (e) {
@ -96,7 +101,7 @@ class TemplateGenerator {
} }
extract(filePath, destinationFolder, cb = () => {}) { extract(filePath, destinationFolder, cb = () => {}) {
utils.extractZip( extractZip(
filePath, filePath,
destinationFolder, destinationFolder,
{ {
@ -139,7 +144,7 @@ class TemplateGenerator {
); );
execSync(`npm pack ${templateSpecifier}`, {cwd: tmpDir, stdio: 'ignore'}); execSync(`npm pack ${templateSpecifier}`, {cwd: tmpDir, stdio: 'ignore'});
const packed = utils.filesMatchingPattern( const packed = filesMatchingPattern(
[joinPath(tmpDir, '*.tgz')] [joinPath(tmpDir, '*.tgz')]
)[0]; )[0];
@ -162,7 +167,7 @@ class TemplateGenerator {
} }
installTemplate(templatePath, name, installPackages, cb) { installTemplate(templatePath, name, installPackages, cb) {
utils.cd(templatePath); shelljs.cd(templatePath);
const pkgJson = fs.readJSONSync('./package.json'); const pkgJson = fs.readJSONSync('./package.json');
if (!(/demo/).test(name)) { if (!(/demo/).test(name)) {
@ -260,7 +265,7 @@ class TemplateGenerator {
let templateAndBranch = uri.split('#'); let templateAndBranch = uri.split('#');
if (templateAndBranch.length === 1) { if (templateAndBranch.length === 1) {
fallback = true; fallback = true;
embarkVersion = semver(require('../../../package.json').version); embarkVersion = semver(require(embarkPath('package.json')).version);
templateAndBranch.push(`${embarkVersion.major}.${embarkVersion.minor}`); templateAndBranch.push(`${embarkVersion.major}.${embarkVersion.minor}`);
} }
templateAndBranch[0] = `embark-framework/embark-${templateAndBranch[0]}-template`; templateAndBranch[0] = `embark-framework/embark-${templateAndBranch[0]}-template`;
@ -306,4 +311,9 @@ class TemplateGenerator {
}); });
} }
} }
module.exports = TemplateGenerator;
function extractZip(filename, packageDirectory, opts, cb) {
decompress(filename, packageDirectory, opts).then((_files) => {
cb();
});
}

View File

@ -2,7 +2,7 @@ require('colors');
// TODO: just logFunction changes, probably doesn't need a whole new module just // TODO: just logFunction changes, probably doesn't need a whole new module just
// for this // for this
class TestLogger { export class TestLogger {
constructor(options) { constructor(options) {
this.logLevels = ['error', 'warn', 'info', 'debug', 'trace']; this.logLevels = ['error', 'warn', 'info', 'debug', 'trace'];
this.logLevel = options.logLevel || 'info'; this.logLevel = options.logLevel || 'info';
@ -52,5 +52,3 @@ class TestLogger {
} }
} }
module.exports = TestLogger;

View File

@ -0,0 +1,9 @@
export function filesMatchingPattern(files) {
const globule = require('globule');
return globule.find(files, {nonull: true});
}
export function fileMatchesPattern(patterns, intendedPath) {
const globule = require('globule');
return globule.isMatch(patterns, intendedPath);
}

View File

@ -0,0 +1,5 @@
{
"extends": "../../../tsconfig.json",
"include": ["src/**/*"]
}

View File

@ -0,0 +1,4 @@
{
"extends": "../../../tslint.json"
}

View File

@ -1,7 +1,7 @@
import { Maybe } from "embark"; import { Maybe } from 'embark';
import * as i18n from "i18n"; import * as i18n from 'i18n';
declare module "embark-i18n" { declare module 'embark-i18n' {
function setOrDetectLocale(locale: Maybe<string>): void; function setOrDetectLocale(locale: Maybe<string>): void;
function __( function __(
phraseOrOptions: string | i18n.TranslateOptions, phraseOrOptions: string | i18n.TranslateOptions,

View File

@ -1,20 +1,20 @@
import colors from "colors/safe"; import colors from 'colors/safe';
import * as i18n from "i18n"; import * as i18n from 'i18n';
import * as osLocale from "os-locale"; import * as osLocale from 'os-locale';
import * as path from "path"; import * as path from 'path';
import { Maybe } /* supplied by @types/embark in packages/embark-typings */ from "embark"; import { Maybe } /* supplied by @types/embark in packages/embark-typings */ from 'embark';
enum LocalType { enum LocalType {
Specified = "specified", Specified = 'specified',
Detected = "detected", Detected = 'detected',
} }
enum SupportedLanguage { enum SupportedLanguage {
En = "en", En = 'en',
Pt = "pt", Pt = 'pt',
Fr = "fr", Fr = 'fr',
Es = "es", Es = 'es',
} }
const DEFAULT_LANGUAGE = SupportedLanguage.En; const DEFAULT_LANGUAGE = SupportedLanguage.En;
@ -22,7 +22,7 @@ const DEFAULT_LANGUAGE = SupportedLanguage.En;
const i18nEmbark = { __: null }; const i18nEmbark = { __: null };
i18n.configure({ i18n.configure({
directory: path.join(__dirname, "../", "locales"), directory: path.join(__dirname, '../', 'locales'),
locales: Object.values(SupportedLanguage), locales: Object.values(SupportedLanguage),
register: i18nEmbark, register: i18nEmbark,
syncFiles: false, syncFiles: false,

View File

@ -7,7 +7,7 @@ const util = require('util');
const DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss:SSS'; const DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss:SSS';
const LOG_REGEX = new RegExp(/\[(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d:\d\d\d)\] (?:\[(\w*)\]:?)?\s?\s?(.*)/gmi); const LOG_REGEX = new RegExp(/\[(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d:\d\d\d)\] (?:\[(\w*)\]:?)?\s?\s?(.*)/gmi);
class Logger { export class Logger {
constructor(options) { constructor(options) {
this.events = options.events || {emit: function(){}}; this.events = options.events || {emit: function(){}};
this.logLevels = Object.keys(Logger.logLevels); this.logLevels = Object.keys(Logger.logLevels);
@ -167,5 +167,3 @@ Logger.prototype.dir = function (txt) {
Logger.prototype.shouldLog = function (level) { Logger.prototype.shouldLog = function (level) {
return (this.logLevels.indexOf(level) <= this.logLevels.indexOf(this.logLevel)); return (this.logLevels.indexOf(level) <= this.logLevels.indexOf(this.logLevel));
}; };
module.exports = Logger;

View File

@ -1,11 +1,11 @@
import "./src/prettier-plugin-solidity"; import './src/prettier-plugin-solidity';
import "./src/remix-debug-debugtest"; import './src/remix-debug-debugtest';
export * from "./src/callbacks"; export * from './src/callbacks';
export * from "./src/contract"; export * from './src/contract';
export * from "./src/embark"; export * from './src/embark';
export * from "./src/contractsConfig"; export * from './src/contractsConfig';
export * from "./src/embarkConfig"; export * from './src/embarkConfig';
export * from "./src/logger"; export * from './src/logger';
export * from "./src/maybe"; export * from './src/maybe';
export * from "./src/plugins"; export * from './src/plugins';

View File

@ -1,4 +1,4 @@
import { ABIDefinition } from "web3/eth/abi"; import { ABIDefinition } from 'web3/eth/abi';
export interface Contract { export interface Contract {
abiDefinition: ABIDefinition[]; abiDefinition: ABIDefinition[];

View File

@ -1,5 +1,5 @@
import { Logger } from "./logger"; import { Logger } from './logger';
import { Plugins } from "./plugins"; import { Plugins } from './plugins';
type CommandCallback = ( type CommandCallback = (
opt1?: any, opt1?: any,

View File

@ -1,4 +1,4 @@
import {Callback} from "./callbacks"; import {Callback} from './callbacks';
export interface Plugin { export interface Plugin {
dappGenerators: any; dappGenerators: any;

View File

@ -1 +1 @@
declare module "prettier-plugin-solidity"; declare module 'prettier-plugin-solidity';

View File

@ -1 +1 @@
declare module "remix-debug-debugtest"; declare module 'remix-debug-debugtest';

View File

@ -13,6 +13,8 @@ declare module "embark-utils" {
function checkIsAvailable(url: string, callback: any): void; function checkIsAvailable(url: string, callback: any): void;
function dockerHostSwap(host: string): string; function dockerHostSwap(host: string): string;
function buildUrl(protocol: string, host: string, port: number, type: string): string; function buildUrl(protocol: string, host: string, port: number, type: string): string;
function buildUrlFromConfig(config: any): string;
function canonicalHost(host: string): string;
function dappPath(...names: string[]): string; function dappPath(...names: string[]): string;
function diagramPath(...names: string[]): string; function diagramPath(...names: string[]): string;
function escapeHtml(message: any): string; function escapeHtml(message: any): string;

View File

@ -52,6 +52,7 @@
"colors": "1.3.2", "colors": "1.3.2",
"core-js": "3.3.5", "core-js": "3.3.5",
"embark-i18n": "^5.0.0-alpha.1", "embark-i18n": "^5.0.0-alpha.1",
"embark-logger": "^5.0.0-alpha.1",
"ethereumjs-wallet": "0.6.3", "ethereumjs-wallet": "0.6.3",
"find-up": "2.1.0", "find-up": "2.1.0",
"follow-redirects": "1.8.0", "follow-redirects": "1.8.0",

View File

@ -9,7 +9,7 @@ const {utils} = require('web3');
const path = require('path'); const path = require('path');
const ERROR_ACCOUNT = 'ERROR_ACCOUNT'; const ERROR_ACCOUNT = 'ERROR_ACCOUNT';
class AccountParser { export default class AccountParser {
static parseAccountsConfig(accountsConfig, web3, dappPath, logger, nodeAccounts) { static parseAccountsConfig(accountsConfig, web3, dappPath, logger, nodeAccounts) {
let accounts = []; let accounts = [];
if (accountsConfig && accountsConfig.length) { if (accountsConfig && accountsConfig.length) {
@ -153,5 +153,3 @@ class AccountParser {
return ERROR_ACCOUNT; return ERROR_ACCOUNT;
} }
} }
module.exports = AccountParser;

View File

@ -1,6 +1,6 @@
const ZERO_ADDRESS_SHORTHAND_REGEX = /^0x0$/; const ZERO_ADDRESS_SHORTHAND_REGEX = /^0x0$/;
const ZERO_ADDRESS_SHORTHAND_SEARCH_REGEX = /'0x0'/g; const ZERO_ADDRESS_SHORTHAND_SEARCH_REGEX = /'0x0'/g;
export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
export function extendZeroAddressShorthand(value: string) { export function extendZeroAddressShorthand(value: string) {
if (value.match(ZERO_ADDRESS_SHORTHAND_REGEX) !== null) { if (value.match(ZERO_ADDRESS_SHORTHAND_REGEX) !== null) {

View File

@ -1,4 +1,4 @@
const merge = require("merge"); const merge = require('merge');
export function last(array: any) { export function last(array: any) {
return array[array.length - 1]; return array[array.length - 1];

View File

@ -1,23 +1,23 @@
import { __ } from "embark-i18n"; import { __ } from 'embark-i18n';
import * as fs from "fs-extra"; import * as fs from 'fs-extra';
import * as path from "path"; import * as path from 'path';
import { downloadFile } from "./network"; import { downloadFile } from './network';
import { dappPath, embarkPath } from "./pathUtils"; import { dappPath, embarkPath } from './pathUtils';
import { ImportRemapping, prepareForCompilation } from "./solidity/remapImports"; import { ImportRemapping, prepareForCompilation } from './solidity/remapImports';
const HTTP_CONTRACTS_DIRECTORY = ".embark/contracts/"; const HTTP_CONTRACTS_DIRECTORY = '.embark/contracts/';
export enum Types { export enum Types {
embarkInternal = "embark_internal", embarkInternal = 'embark_internal',
dappFile = "dapp_file", dappFile = 'dapp_file',
custom = "custom", custom = 'custom',
http = "http", http = 'http',
} }
export class File { export class File {
public type: Types; public type: Types;
public externalUrl: string = ""; public externalUrl: string = '';
public path = ""; public path = '';
public basedir: string; public basedir: string;
public resolver: (callback: (content: string) => void) => void; public resolver: (callback: (content: string) => void) => void;
public pluginPath: string; public pluginPath: string;
@ -29,16 +29,16 @@ export class File {
constructor(options: any) { constructor(options: any) {
this.type = options.type; this.type = options.type;
this.basedir = options.basedir || ""; this.basedir = options.basedir || '';
this.resolver = options.resolver; this.resolver = options.resolver;
this.pluginPath = options.pluginPath ? options.pluginPath : ""; this.pluginPath = options.pluginPath ? options.pluginPath : '';
this.storageConfig = options.storageConfig; this.storageConfig = options.storageConfig;
this.providerUrl = ""; this.providerUrl = '';
this.originalPath = options.originalPath || ""; this.originalPath = options.originalPath || '';
if (this.type === Types.custom && this.pluginPath) { if (this.type === Types.custom && this.pluginPath) {
this.path = path.join(this.pluginPath, options.path).replace(dappPath(), ""); this.path = path.join(this.pluginPath, options.path).replace(dappPath(), '');
if (this.path.startsWith("/")) { if (this.path.startsWith('/')) {
this.path = this.path.substring(1); this.path = this.path.substring(1);
} }
} else if (this.type === Types.http) { } else if (this.type === Types.http) {
@ -53,8 +53,8 @@ export class File {
} }
public async prepareForCompilation(isCoverage = false) { public async prepareForCompilation(isCoverage = false) {
if (!this.path.endsWith(".sol")) { if (!this.path.endsWith('.sol')) {
return Promise.reject(__("This method is only supported for Solidity files")); return Promise.reject(__('This method is only supported for Solidity files'));
} }
return prepareForCompilation(this, isCoverage); return prepareForCompilation(this, isCoverage);
} }
@ -63,12 +63,12 @@ export class File {
return new Promise<string>((resolve) => { return new Promise<string>((resolve) => {
switch (this.type) { switch (this.type) {
case Types.embarkInternal: { case Types.embarkInternal: {
const content = fs.readFileSync(embarkPath(path.join("dist", this.path)), "utf-8"); const content = fs.readFileSync(embarkPath(path.join('dist', this.path)), 'utf-8');
return resolve(content); return resolve(content);
} }
case Types.dappFile: { case Types.dappFile: {
const content = fs.readFileSync(this.path, "utf-8").toString(); const content = fs.readFileSync(this.path, 'utf-8').toString();
return resolve(content); return resolve(content);
} }
@ -81,7 +81,7 @@ export class File {
case Types.http: { case Types.http: {
fs.ensureFileSync(this.path); fs.ensureFileSync(this.path);
return downloadFile(this.externalUrl, this.path, () => { return downloadFile(this.externalUrl, this.path, () => {
const content = fs.readFileSync(this.path, "utf-8"); const content = fs.readFileSync(this.path, 'utf-8');
resolve(content); resolve(content);
}); });
} }
@ -93,20 +93,20 @@ export class File {
export function getExternalContractUrl(file: string, providerUrl: string) { export function getExternalContractUrl(file: string, providerUrl: string) {
let url; let url;
const RAW_URL = "https://raw.githubusercontent.com/"; const RAW_URL = 'https://raw.githubusercontent.com/';
const DEFAULT_SWARM_GATEWAY = "https://swarm-gateways.net/"; const DEFAULT_SWARM_GATEWAY = 'https://swarm-gateways.net/';
const MALFORMED_SWARM_ERROR = "Malformed Swarm gateway URL for "; const MALFORMED_SWARM_ERROR = 'Malformed Swarm gateway URL for ';
const MALFORMED_ERROR = "Malformed Github URL for "; const MALFORMED_ERROR = 'Malformed Github URL for ';
const MALFORMED_IPFS_ERROR = "Malformed IPFS URL for "; const MALFORMED_IPFS_ERROR = 'Malformed IPFS URL for ';
const IPFS_GETURL_NOTAVAILABLE = "IPFS getUrl is not available. Please set it in your storage config. For more info: https://embark.status.im/docs/storage_configuration.html"; const IPFS_GETURL_NOTAVAILABLE = 'IPFS getUrl is not available. Please set it in your storage config. For more info: https://embark.status.im/docs/storage_configuration.html';
if (file.startsWith("https://github")) { if (file.startsWith('https://github')) {
const file_path = file.match(/https:\/\/github\.[a-z]+\/(.*)/); const file_path = file.match(/https:\/\/github\.[a-z]+\/(.*)/);
if (!file_path) { if (!file_path) {
console.error(MALFORMED_ERROR + file); console.error(MALFORMED_ERROR + file);
return null; return null;
} }
url = `${RAW_URL}${file_path[1].replace("blob/", "")}`; url = `${RAW_URL}${file_path[1].replace('blob/', '')}`;
} else if (file.startsWith("ipfs")) { } else if (file.startsWith('ipfs')) {
if (!providerUrl) { if (!providerUrl) {
console.error(IPFS_GETURL_NOTAVAILABLE); console.error(IPFS_GETURL_NOTAVAILABLE);
return null; return null;
@ -121,14 +121,14 @@ export function getExternalContractUrl(file: string, providerUrl: string) {
} }
let matchResult = file_path[1]; let matchResult = file_path[1];
if (file_path[2]) { if (file_path[2]) {
matchResult += "/" + file_path[2]; matchResult += '/' + file_path[2];
} }
url = `${providerUrl}${matchResult}`; url = `${providerUrl}${matchResult}`;
return { return {
filePath: HTTP_CONTRACTS_DIRECTORY + matchResult, filePath: HTTP_CONTRACTS_DIRECTORY + matchResult,
url, url,
}; };
} else if (file.startsWith("git")) { } else if (file.startsWith('git')) {
// Match values // Match values
// [0] entire input // [0] entire input
// [1] git:// // [1] git://
@ -145,12 +145,12 @@ export function getExternalContractUrl(file: string, providerUrl: string) {
} }
let branch = file_path[5]; let branch = file_path[5];
if (!branch) { if (!branch) {
branch = "master"; branch = 'master';
} }
url = `${RAW_URL}${file_path[2]}/${file_path[3]}/${branch}/${file_path[4]}`; url = `${RAW_URL}${file_path[2]}/${file_path[3]}/${branch}/${file_path[4]}`;
} else if (file.startsWith("http")) { } else if (file.startsWith('http')) {
url = file; url = file;
} else if (file.startsWith("bzz")) { } else if (file.startsWith('bzz')) {
if (!providerUrl) { if (!providerUrl) {
url = DEFAULT_SWARM_GATEWAY + file; url = DEFAULT_SWARM_GATEWAY + file;
} else { } else {
@ -162,7 +162,7 @@ export function getExternalContractUrl(file: string, providerUrl: string) {
return null; return null;
} }
} }
url = providerUrl + "/" + file; url = providerUrl + '/' + file;
} }
} else { } else {
return null; return null;
@ -171,7 +171,7 @@ export function getExternalContractUrl(file: string, providerUrl: string) {
/\.[a-z]+\/([-a-zA-Z0-9@:%_+.~#?&\/=]+)/, /\.[a-z]+\/([-a-zA-Z0-9@:%_+.~#?&\/=]+)/,
); );
return { return {
filePath: HTTP_CONTRACTS_DIRECTORY + (match !== null ? match[1] : ""), filePath: HTTP_CONTRACTS_DIRECTORY + (match !== null ? match[1] : ''),
url, url,
}; };
} }

View File

@ -1,17 +1,17 @@
const {execSync} = require("child_process"); const {execSync} = require('child_process');
const {hostname} = require("os"); const {hostname} = require('os');
const isDocker = (() => { const isDocker = (() => {
// assumption: an Embark container is always a Linux Docker container, though // assumption: an Embark container is always a Linux Docker container, though
// the Docker host may be Linux, macOS, or Windows // the Docker host may be Linux, macOS, or Windows
if (process.platform !== "linux") { return false; } if (process.platform !== 'linux') { return false; }
try { try {
return ( return (
new RegExp(`[0-9]+\:[a-z_-]+\:\/docker\/${hostname()}[0-9a-z]+`, "i") new RegExp(`[0-9]+\:[a-z_-]+\:\/docker\/${hostname()}[0-9a-z]+`, 'i')
).test( ).test(
execSync( execSync(
"cat /proc/self/cgroup", 'cat /proc/self/cgroup',
{stdio: ["ignore", "pipe", "ignore"]}, {stdio: ['ignore', 'pipe', 'ignore']},
).toString(), ).toString(),
); );
} catch (e) { } catch (e) {
@ -19,18 +19,18 @@ const isDocker = (() => {
} }
})(); })();
const defaultHost = isDocker ? "0.0.0.0" : "localhost"; const defaultHost = isDocker ? '0.0.0.0' : 'localhost';
// when we're runing in Docker, we can expect (generally, in a development // when we're runing in Docker, we can expect (generally, in a development
// scenario) that the user would like to connect to the service in the // scenario) that the user would like to connect to the service in the
// container via the **host's** loopback address, so this helper can be used to // container via the **host's** loopback address, so this helper can be used to
// swap 0.0.0.0 for localhost in code/messages that pertain to client-side // swap 0.0.0.0 for localhost in code/messages that pertain to client-side
function canonicalHost(host: string): string { function canonicalHost(host: string): string {
return isDocker && host === "0.0.0.0" ? "localhost" : host; return isDocker && host === '0.0.0.0' ? 'localhost' : host;
} }
function dockerHostSwap(host: string): string { function dockerHostSwap(host: string): string {
return (isDocker && (host === "localhost" || host === "127.0.0.1")) ? defaultHost : host; return (isDocker && (host === 'localhost' || host === '127.0.0.1')) ? defaultHost : host;
} }
const defaultCorsHost = canonicalHost(defaultHost); const defaultCorsHost = canonicalHost(defaultHost);

View File

@ -3,27 +3,36 @@ const https = require('follow-redirects').https;
const shelljs = require('shelljs'); const shelljs = require('shelljs');
const clipboardy = require('clipboardy'); const clipboardy = require('clipboardy');
const {canonicalHost, defaultCorsHost, defaultHost, dockerHostSwap, isDocker} = require('./host'); import { canonicalHost } from './host';
const {downloadFile, findNextPort, getJson, httpGet, httpsGet, httpGetJson, httpsGetJson, pingEndpoint} = require('./network'); export { canonicalHost, defaultCorsHost, defaultHost, dockerHostSwap, isDocker } from './host';
export { downloadFile, findNextPort, getJson, httpGet, httpsGet, httpGetJson, httpsGetJson, pingEndpoint } from './network';
const logUtils = require('./log-utils'); const logUtils = require('./log-utils');
export const escapeHtml = logUtils.escapeHtml;
export const normalizeInput = logUtils.normalizeInput;
export { LogHandler } from './logHandler';
const toposortGraph = require('./toposort'); const toposortGraph = require('./toposort');
import { unitRegex } from './constants';
import * as AddressUtils from './addressUtils'; import * as AddressUtils from './addressUtils';
import { export { AddressUtils };
getWeiBalanceFromString, import { unitRegex } from './constants';
getHexBalanceFromString, export { unitRegex } from './constants';
hexToNumber, import { isHex, getWeiBalanceFromString } from './web3Utils';
export {
decodeParams, decodeParams,
isHex,
getHexBalanceFromString,
getWeiBalanceFromString,
hexToNumber,
sha3, sha3,
sha512, sha512,
isHex,
soliditySha3, soliditySha3,
toChecksumAddress toChecksumAddress
} from './web3Utils'; } from './web3Utils';
import { getAddressToContract, getTransactionParams } from './transactionUtils'; export { getAddressToContract, getTransactionParams } from './transactionUtils';
import LongRunningProcessTimer from './longRunningProcessTimer'; import LongRunningProcessTimer from './longRunningProcessTimer';
export { LongRunningProcessTimer };
import AccountParser from './accountParser'; import AccountParser from './accountParser';
import { export { AccountParser };
export {
anchoredValue, anchoredValue,
dappPath, dappPath,
diagramPath, diagramPath,
@ -42,15 +51,15 @@ import {
normalizePath, normalizePath,
toForwardSlashes toForwardSlashes
} from './pathUtils'; } from './pathUtils';
import { setUpEnv } from './env'; export { setUpEnv } from './env';
const { extendZeroAddressShorthand, replaceZeroAddressShorthand } = AddressUtils; const { extendZeroAddressShorthand, replaceZeroAddressShorthand } = AddressUtils;
import { compact, last, recursiveMerge, groupBy } from './collections'; export { compact, last, recursiveMerge, groupBy } from './collections';
import { prepareForCompilation } from './solidity/remapImports'; export { prepareForCompilation } from './solidity/remapImports';
import { File, getExternalContractUrl, Types } from './file'; export { File, getExternalContractUrl, Types } from './file';
import { export {
findMonorepoPackageFromRoot, findMonorepoPackageFromRoot,
findMonorepoPackageFromRootSync, findMonorepoPackageFromRootSync,
isInsideMonorepo, isInsideMonorepo,
@ -59,25 +68,23 @@ import {
monorepoRootPathSync monorepoRootPathSync
} from './monorepo'; } from './monorepo';
function timer(ms) { export function timer(ms: number) {
const then = Date.now(); const then = Date.now();
return new Promise(resolve => ( return new Promise(resolve => (
setTimeout(() => resolve(Date.now() - then), ms) setTimeout(() => resolve(Date.now() - then), ms)
)); ));
} }
function checkIsAvailable(url, callback) { export function checkIsAvailable(url: string, callback: (isAvailable: boolean) => void) {
const protocol = url.split(':')[0]; const protocol = url.split(':')[0];
const httpObj = (protocol === 'https') ? https : http; const httpObj = (protocol === 'https') ? https : http;
httpObj.get(url, function (_res) { httpObj
callback(true); .get(url, (_res: any) => callback(true))
}).on('error', function (_res) { .on('error', (_res: any) => callback(false));
callback(false);
});
} }
function hashTo32ByteHexString(hash) { export function hashTo32ByteHexString(hash: string) {
if (isHex(hash)) { if (isHex(hash)) {
if (!hash.startsWith('0x')) { if (!hash.startsWith('0x')) {
hash = '0x' + hash; hash = '0x' + hash;
@ -85,84 +92,84 @@ function hashTo32ByteHexString(hash) {
return hash; return hash;
} }
const multihash = require('multihashes'); const multihash = require('multihashes');
let buf = multihash.fromB58String(hash); const buf = multihash.fromB58String(hash);
let digest = multihash.decode(buf).digest; const digest = multihash.decode(buf).digest;
return '0x' + multihash.toHexString(digest); return '0x' + multihash.toHexString(digest);
} }
function exit(code) { export function exit(code: number) {
process.exit(code); process.exit(code);
} }
function runCmd(cmd, options, callback) { export function runCmd(cmd: string, options: any, callback: any) {
options = Object.assign({silent: true, exitOnError: true, async: true}, options || {}); options = Object.assign({silent: true, exitOnError: true, async: true}, options || {});
const outputToConsole = !options.silent; const outputToConsole = !options.silent;
options.silent = true; options.silent = true;
let result = shelljs.exec(cmd, options, function (code, stdout) { const result = shelljs.exec(cmd, options, (code, stdout: string) => {
if(code !== 0) { if (code !== 0) {
if (options.exitOnError) { if (options.exitOnError) {
return exit(); return exit(code);
} }
if(typeof callback === 'function') { if (typeof callback === 'function') {
callback(`shell returned code ${code}`); callback(`shell returned code ${code}`);
} }
} else { } else {
if(typeof callback === 'function') { if (typeof callback === 'function') {
return callback(null, stdout); return callback(null, stdout);
} }
} }
}); });
result.stdout.on('data', function(data) { result.stdout.on('data', (data: any) => {
if(outputToConsole) { if (outputToConsole) {
console.log(data); console.log(data);
} }
}); });
result.stderr.on('data', function(data) { result.stderr.on('data', (data: any) => {
if (outputToConsole) { if (outputToConsole) {
console.log(data); console.log(data);
} }
}); });
} }
function copyToClipboard(text) { export function copyToClipboard(text: string) {
clipboardy.writeSync(text); clipboardy.writeSync(text);
} }
function byName(a, b) { export function byName(a, b) {
return a.name.localeCompare(b.name); return a.name.localeCompare(b.name);
} }
function isFolder(node) { export function isFolder(node) {
return node.children && node.children.length; return node.children && node.children.length;
} }
function isNotFolder(node){ export function isNotFolder(node) {
return !isFolder(node); return !isFolder(node);
} }
function fileTreeSort(nodes){ export function fileTreeSort(nodes) {
const folders = nodes.filter(isFolder).sort(byName); const folders = nodes.filter(isFolder).sort(byName);
const files = nodes.filter(isNotFolder).sort(byName); const files = nodes.filter(isNotFolder).sort(byName);
return folders.concat(files); return folders.concat(files);
} }
function proposeAlternative(word, _dictionary, _exceptions) { export function proposeAlternative(word, _dictionary, _exceptions) {
const propose = require('propose'); const propose = require('propose');
let exceptions = _exceptions || []; const exceptions = _exceptions || [];
let dictionary = _dictionary.filter((entry) => { const dictionary = _dictionary.filter((entry) => {
return exceptions.indexOf(entry) < 0; return exceptions.indexOf(entry) < 0;
}); });
return propose(word, dictionary, {threshold: 0.3}); return propose(word, dictionary, {threshold: 0.3});
} }
function toposort(graph) { export function toposort(graph) {
return toposortGraph(graph); return toposortGraph(graph);
} }
function deconstructUrl(endpoint) { export function deconstructUrl(endpoint) {
const matches = endpoint.match(/(wss?|https?):\/\/([a-zA-Z0-9_.\/-]*):?([0-9]*)?/); const matches = endpoint.match(/(wss?|https?):\/\/([a-zA-Z0-9_.\/-]*):?([0-9]*)?/);
return { return {
protocol: matches[1], protocol: matches[1],
@ -172,7 +179,7 @@ function deconstructUrl(endpoint) {
}; };
} }
function prepareContractsConfig(config) { export function prepareContractsConfig(config) {
if (config.deploy) { if (config.deploy) {
config.contracts = config.deploy; config.contracts = config.deploy;
delete config.deploy; delete config.deploy;
@ -213,7 +220,7 @@ function prepareContractsConfig(config) {
return config; return config;
} }
function jsonFunctionReplacer(_key, value) { export function jsonFunctionReplacer(_key, value) {
if (typeof value === 'function') { if (typeof value === 'function') {
return value.toString(); return value.toString();
} }
@ -221,9 +228,11 @@ function jsonFunctionReplacer(_key, value) {
return value; return value;
} }
function fuzzySearch(text, list, filter) { export function fuzzySearch(text, list, filter) {
const fuzzy = require('fuzzy'); const fuzzy = require('fuzzy');
return fuzzy.filter(text, list, {extract: (filter || function () {})}); return fuzzy.filter(text, list, {
extract: filter
});
} }
/** /**
@ -239,10 +248,15 @@ function fuzzySearch(text, list, filter) {
* Type of connection * Type of connection
* @returns {string} the constructued URL, with defaults * @returns {string} the constructued URL, with defaults
*/ */
function buildUrl(protocol, host, port, type) { export function buildUrl(protocol, host, port, type) {
if (!host) throw new Error('utils.buildUrl: parameter \'host\' is required'); if (!host) {
if (port) port = ':' + port; throw new Error('utils.buildUrl: parameter \'host\' is required');
else port = ''; }
if (port) {
port = ':' + port;
} else {
port = '';
}
if (!protocol) { if (!protocol) {
protocol = type === 'ws' ? 'ws' : 'http'; protocol = type === 'ws' ? 'ws' : 'http';
} }
@ -258,13 +272,17 @@ function buildUrl(protocol, host, port, type) {
* * port {String} (optional) The URL port, default to empty string. * * port {String} (optional) The URL port, default to empty string.
* @returns {string} the constructued URL, with defaults * @returns {string} the constructued URL, with defaults
*/ */
function buildUrlFromConfig(configObj) { export function buildUrlFromConfig(configObj) {
if (!configObj) throw new Error('[utils.buildUrlFromConfig]: config object must cannot be null'); if (!configObj) {
if (!configObj.host) throw new Error('[utils.buildUrlFromConfig]: object must contain a \'host\' property'); throw new Error('[utils.buildUrlFromConfig]: config object must cannot be null');
}
if (!configObj.host) {
throw new Error('[utils.buildUrlFromConfig]: object must contain a \'host\' property');
}
return buildUrl(configObj.protocol, canonicalHost(configObj.host), configObj.port, configObj.type); return buildUrl(configObj.protocol, canonicalHost(configObj.host), configObj.port, configObj.type);
} }
function errorMessage(e) { export function errorMessage(e) {
if (typeof e === 'string') { if (typeof e === 'string') {
return e; return e;
} else if (e && e.message) { } else if (e && e.message) {
@ -273,95 +291,10 @@ function errorMessage(e) {
return e; return e;
} }
function isConstructor(obj) { export function isConstructor(obj) {
return !!obj.prototype && !!obj.prototype.constructor.name; return !!obj.prototype && !!obj.prototype.constructor.name;
} }
function isEs6Module(module) { export function isEs6Module(module) {
return (typeof module === 'function' && isConstructor(module)) || (typeof module === 'object' && typeof module.default === 'function' && module.__esModule); return (typeof module === 'function' && isConstructor(module)) || (typeof module === 'object' && typeof module.default === 'function' && module.__esModule);
} }
const Utils = {
anchoredValue,
buildUrl,
buildUrlFromConfig,
joinPath,
tmpDir,
ipcPath,
dappPath,
downloadFile,
embarkPath,
normalizePath,
toForwardSlashes,
jsonFunctionReplacer,
fuzzySearch,
canonicalHost,
compact,
copyToClipboard,
diagramPath,
deconstructUrl,
defaultCorsHost,
defaultHost,
decodeParams,
dockerHostSwap,
exit,
errorMessage,
getAddressToContract,
getTransactionParams,
isDocker,
isEs6Module,
checkIsAvailable,
File,
findNextPort,
fileTreeSort,
hashTo32ByteHexString,
hexToNumber,
isHex,
last,
soliditySha3,
recursiveMerge,
prepareContractsConfig,
findMonorepoPackageFromRoot,
findMonorepoPackageFromRootSync,
getWeiBalanceFromString,
getHexBalanceFromString,
getExternalContractUrl,
getJson,
groupBy,
httpGet,
httpsGet,
httpGetJson,
httpsGetJson,
isInsideMonorepo,
isInsideMonorepoSync,
monorepoRootPath,
monorepoRootPathSync,
pingEndpoint,
setUpEnv,
sha512,
sha3,
timer,
Types,
unitRegex,
urlJoin,
runCmd,
escapeHtml: logUtils.escapeHtml,
normalizeInput: logUtils.normalizeInput,
LogHandler: require('./logHandler'),
LongRunningProcessTimer,
pkgPath,
prepareForCompilation,
proposeAlternative,
toChecksumAddress,
toposort,
AddressUtils,
AccountParser,
PWD,
DAPP_PATH,
DIAGRAM_PATH,
EMBARK_PATH,
PKG_PATH,
NODE_PATH
};
module.exports = Utils;

View File

@ -7,7 +7,7 @@ const MAX_LOGS = 1500; // TODO use constants when it's put in a package or somet
/** /**
* Serves as a central point of log handling. * Serves as a central point of log handling.
*/ */
class LogHandler { export class LogHandler {
/** /**
* @param {Object} options Options object containing: * @param {Object} options Options object containing:
@ -97,5 +97,3 @@ class LogHandler {
}); });
} }
} }
module.exports = LogHandler;

View File

@ -1,5 +1,5 @@
import { red } from "colors"; import { red } from "colors";
import { Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark"; import { Logger } from 'embark-logger';
import { performance, PerformanceObserver } from "perf_hooks"; import { performance, PerformanceObserver } from "perf_hooks";
import prettyMs from "pretty-ms"; import prettyMs from "pretty-ms";
import { last, recursiveMerge } from "./collections"; import { last, recursiveMerge } from "./collections";

View File

@ -194,26 +194,6 @@ class Cmd {
} }
blockchain() { blockchain() {
// program
// .command('blockchain [environment]')
// .option('-c, --client [client]', __('Use a specific ethereum client [%s] (default: %s)', 'geth, parity', 'geth'))
// .option('--locale [locale]', __('language to use (default: en)'))
// .description(__('run blockchain server (default: %s)', 'development'))
// .action(function(env, options) {
// setOrDetectLocale(options.locale);
// embark.initConfig(env || 'development', {
// embarkConfig: 'embark.json',
// interceptLogs: false
// });
// if (embark.config.blockchainConfig.endpoint && !embark.config.blockchainConfig.isAutoEndpoint) {
// embark.logger.warn(__('You are starting the blockchain node, but have an `endpoint` specified. `embark run` is probably what you wanted to run'));
// }
// embark.blockchain(env || 'development', options.client);
// });
// TODO: fix me, re-add above
program program
.command('blockchain [environment]') .command('blockchain [environment]')
.option('-p, --port [port]', __('port to run the dev webserver (default: %s)', '8000')) .option('-p, --port [port]', __('port to run the dev webserver (default: %s)', '8000'))

View File

@ -1,20 +1,22 @@
import {__} from 'embark-i18n'; import { Config, Engine, Events, fs, TemplateGenerator } from 'embark-core';
import {dappPath, embarkPath} from 'embark-utils'; import { __ } from 'embark-i18n';
import { dappPath, embarkPath, joinPath, setUpEnv } from 'embark-utils';
import { Logger } from 'embark-logger';
let async = require('async'); let async = require('async');
const constants = require('embark-core/constants'); const constants = require('embark-core/constants');
const Logger = require('embark-logger');
const {reset: embarkReset, paths: defaultResetPaths} = require('embark-reset'); const {reset: embarkReset, paths: defaultResetPaths} = require('embark-reset');
const fs = require('../lib/core/fs.js');
const cloneDeep = require('clone-deep'); const cloneDeep = require('clone-deep');
setUpEnv(joinPath(__dirname, '../../'));
require('colors'); require('colors');
let version = require('../../package.json').version; let pkg = require('../../package.json');
class EmbarkController { class EmbarkController {
constructor(options) { constructor(options) {
this.version = version; this.version = pkg.version;
this.options = options || {}; this.options = options || {};
// set a default context. should be overwritten by an action // set a default context. should be overwritten by an action
@ -23,12 +25,10 @@ class EmbarkController {
} }
initConfig(env, options) { initConfig(env, options) {
let Events = require('../lib/core/events.js');
let Config = require('../lib/core/config.js');
this.events = new Events(); this.events = new Events();
this.logger = new Logger({logLevel: Logger.logLevels.debug, events: this.events, context: this.context}); this.logger = new Logger({logLevel: Logger.logLevels.debug, events: this.events, context: this.context});
this.logger.info('foo');
this.config = new Config({env: env, logger: this.logger, events: this.events, context: this.context, version: this.version}); this.config = new Config({env: env, logger: this.logger, events: this.events, context: this.context, version: this.version});
this.config.loadConfigFiles(options); this.config.loadConfigFiles(options);
this.plugins = this.config.plugins; this.plugins = this.config.plugins;
@ -38,7 +38,6 @@ class EmbarkController {
this.context = options.context || [constants.contexts.blockchain]; this.context = options.context || [constants.contexts.blockchain];
const webServerConfig = {}; const webServerConfig = {};
const Engine = require('../lib/core/engine.js');
const engine = new Engine({ const engine = new Engine({
env: options.env, env: options.env,
client: options.client, client: options.client,
@ -52,7 +51,8 @@ class EmbarkController {
webServerConfig: webServerConfig, webServerConfig: webServerConfig,
webpackConfigName: options.webpackConfigName, webpackConfigName: options.webpackConfigName,
singleUseAuthToken: options.singleUseAuthToken, singleUseAuthToken: options.singleUseAuthToken,
ipcRole: 'server' ipcRole: 'server',
package: pkg
}); });
engine.init({}, () => { engine.init({}, () => {
@ -87,7 +87,6 @@ class EmbarkController {
generateTemplate(templateName, destinationFolder, name, url) { generateTemplate(templateName, destinationFolder, name, url) {
this.context = [constants.contexts.templateGeneration]; this.context = [constants.contexts.templateGeneration];
let TemplateGenerator = require('../lib/utils/template_generator.js');
let templateGenerator = new TemplateGenerator(templateName); let templateGenerator = new TemplateGenerator(templateName);
if (url) { if (url) {
@ -119,7 +118,6 @@ class EmbarkController {
webServerConfig.openBrowser = options.openBrowser; webServerConfig.openBrowser = options.openBrowser;
} }
const Engine = require('../lib/core/engine.js');
const engine = new Engine({ const engine = new Engine({
env: options.env, env: options.env,
client: options.client, client: options.client,
@ -133,7 +131,8 @@ class EmbarkController {
webServerConfig: webServerConfig, webServerConfig: webServerConfig,
webpackConfigName: options.webpackConfigName, webpackConfigName: options.webpackConfigName,
singleUseAuthToken: options.singleUseAuthToken, singleUseAuthToken: options.singleUseAuthToken,
ipcRole: 'server' ipcRole: 'server',
package: pkg
}); });
async.waterfall([ async.waterfall([
@ -240,7 +239,6 @@ class EmbarkController {
build(options) { build(options) {
this.context = options.context || [constants.contexts.build]; this.context = options.context || [constants.contexts.build];
const Engine = require('../lib/core/engine.js');
const engine = new Engine({ const engine = new Engine({
env: options.env, env: options.env,
client: options.client, client: options.client,
@ -253,7 +251,8 @@ class EmbarkController {
logger: options.logger, logger: options.logger,
config: options.config, config: options.config,
context: this.context, context: this.context,
webpackConfigName: options.webpackConfigName webpackConfigName: options.webpackConfigName,
package: pkg
}); });
@ -340,7 +339,6 @@ class EmbarkController {
console(options) { console(options) {
this.context = options.context || [constants.contexts.run, constants.contexts.console]; this.context = options.context || [constants.contexts.run, constants.contexts.console];
const REPL = require('./dashboard/repl.js'); const REPL = require('./dashboard/repl.js');
const Engine = require('../lib/core/engine.js');
const engine = new Engine({ const engine = new Engine({
env: options.env, env: options.env,
client: options.client, client: options.client,
@ -351,7 +349,8 @@ class EmbarkController {
logLevel: options.logLevel, logLevel: options.logLevel,
context: this.context, context: this.context,
singleUseAuthToken: options.singleUseAuthToken, singleUseAuthToken: options.singleUseAuthToken,
webpackConfigName: options.webpackConfigName webpackConfigName: options.webpackConfigName,
package: pkg
}); });
const isSecondaryProcess = (engine) => {return engine.ipc.connected && engine.ipc.isClient();}; const isSecondaryProcess = (engine) => {return engine.ipc.connected && engine.ipc.isClient();};
@ -449,13 +448,13 @@ class EmbarkController {
this.context = options.context || [constants.contexts.graph]; this.context = options.context || [constants.contexts.graph];
options.onlyCompile = true; options.onlyCompile = true;
const Engine = require('../lib/core/engine.js');
const engine = new Engine({ const engine = new Engine({
env: options.env, env: options.env,
version: this.version, version: this.version,
embarkConfig: options.embarkConfig || 'embark.json', embarkConfig: options.embarkConfig || 'embark.json',
logFile: options.logFile, logFile: options.logFile,
context: this.context context: this.context,
package: pkg
}); });
async.waterfall([ async.waterfall([
@ -545,7 +544,6 @@ class EmbarkController {
scaffold(options) { scaffold(options) {
this.context = options.context || [constants.contexts.scaffold]; this.context = options.context || [constants.contexts.scaffold];
const Engine = require('../lib/core/engine.js');
const engine = new Engine({ const engine = new Engine({
env: options.env, env: options.env,
client: options.client, client: options.client,
@ -560,7 +558,8 @@ class EmbarkController {
config: options.config, config: options.config,
plugins: options.plugins, plugins: options.plugins,
context: this.context, context: this.context,
webpackConfigName: options.webpackConfigName webpackConfigName: options.webpackConfigName,
package: pkg
}); });
async.waterfall([ async.waterfall([
@ -617,7 +616,6 @@ class EmbarkController {
upload(options) { upload(options) {
this.context = options.context || [constants.contexts.upload, constants.contexts.build]; this.context = options.context || [constants.contexts.upload, constants.contexts.build];
const Engine = require('../lib/core/engine.js');
const engine = new Engine({ const engine = new Engine({
env: options.env, env: options.env,
client: options.client, client: options.client,
@ -632,7 +630,8 @@ class EmbarkController {
config: options.config, config: options.config,
plugins: options.plugins, plugins: options.plugins,
context: this.context, context: this.context,
webpackConfigName: options.webpackConfigName webpackConfigName: options.webpackConfigName,
package: pkg
}); });
let platform; let platform;
@ -714,7 +713,6 @@ class EmbarkController {
runTests(options) { runTests(options) {
this.context = [constants.contexts.test]; this.context = [constants.contexts.test];
const Engine = require('../lib/core/engine.js');
const engine = new Engine({ const engine = new Engine({
env: options.env, env: options.env,
client: options.client, client: options.client,
@ -727,7 +725,8 @@ class EmbarkController {
useDashboard: false, useDashboard: false,
webpackConfigName: options.webpackConfigName, webpackConfigName: options.webpackConfigName,
ipcRole: 'client', ipcRole: 'client',
interceptLogs: false interceptLogs: false,
package: pkg
}); });
async.waterfall([ async.waterfall([
@ -768,6 +767,7 @@ class EmbarkController {
module.exports = EmbarkController; module.exports = EmbarkController;
async function compileAndDeploySmartContracts(engine) { async function compileAndDeploySmartContracts(engine) {
try {
let contractsFiles = await engine.events.request2("config:contractsFiles"); let contractsFiles = await engine.events.request2("config:contractsFiles");
let compiledContracts = await engine.events.request2("compiler:contracts:compile", contractsFiles); let compiledContracts = await engine.events.request2("compiler:contracts:compile", contractsFiles);
let _contractsConfig = await engine.events.request2("config:contractsConfig"); let _contractsConfig = await engine.events.request2("config:contractsConfig");
@ -776,6 +776,9 @@ async function compileAndDeploySmartContracts(engine) {
await engine.events.request2("deployment:contracts:deploy", contractsList, contractDependencies); await engine.events.request2("deployment:contracts:deploy", contractsList, contractDependencies);
await engine.events.request2('pipeline:generateAll'); await engine.events.request2('pipeline:generateAll');
engine.events.emit('outputDone'); engine.events.emit('outputDone');
} catch (e) {
console.log(e);
}
} }
async function setupCargoAndWatcher(engine) { async function setupCargoAndWatcher(engine) {

View File

@ -1,5 +1,12 @@
import { __ } from 'embark-i18n'; import { __ } from 'embark-i18n';
const { getWindowSize } = require('../../lib/utils/utils.js'); import windowSize from 'window-size';
function getWindowSize() {
if (windowSize) {
return windowSize.get();
}
return {width: 240, height: 75};
}
let Monitor = require('./monitor.js'); let Monitor = require('./monitor.js');

View File

@ -1,724 +0,0 @@
const fs = require('./fs.js');
const Plugins = require('./plugins.js');
const utils = require('../utils/utils.js');
const path = require('path');
const deepEqual = require('deep-equal');
const web3 = require('web3');
const constants = require('embark-core/constants');
import { __ } from 'embark-i18n';
import {
buildUrlFromConfig,
canonicalHost,
dappPath,
defaultHost,
File,
Types,
recursiveMerge,
AddressUtils,
unitRegex,
getWeiBalanceFromString,
prepareContractsConfig,
getExternalContractUrl
} from 'embark-utils';
const cloneDeep = require('lodash.clonedeep');
const { replaceZeroAddressShorthand } = AddressUtils;
import {getBlockchainDefaults, getContractDefaults} from './configDefaults';
const DEFAULT_CONFIG_PATH = 'config/';
const PACKAGE = require('../../../package.json');
const embark5ChangesUrl = 'https://embark.status.im/docs/migrating_from_3.x.html#Updating-to-v5';
var Config = function(options) {
this.env = options.env || 'default';
this.blockchainConfig = {};
this.contractsConfig = {};
this.pipelineConfig = {};
this.namesystemConfig = {};
this.communicationConfig = {};
this.webServerConfig = options.webServerConfig;
this.chainTracker = {};
this.assetFiles = {};
this.contractsFiles = [];
this.configDir = options.configDir || DEFAULT_CONFIG_PATH;
this.chainsFile = options.chainsFile || './chains.json';
this.plugins = options.plugins;
this.logger = options.logger;
this.package = PACKAGE;
this.events = options.events;
this.embarkConfig = {};
this.context = options.context || [constants.contexts.any];
this.version = options.version;
this.shownNoAccountConfigMsg = false; // flag to ensure "no account config" message is only displayed once to the user
this.corsParts = [];
this.providerUrl = null;
this.registerEvents();
};
Config.prototype.setConfig = function(configName, newConfig, cb) {
this[configName] = newConfig;
cb();
};
Config.prototype.registerEvents = function() {
this.events.setCommandHandler("config:cors:add", (url) => {
this.corsParts.push(url);
this._updateBlockchainCors();
});
this.events.setCommandHandler("config:contractsConfig", (cb) => {
cb(null, this.contractsConfig);
});
this.events.setCommandHandler("config:storageConfig", (cb) => {
cb(null, this.storageConfig);
});
this.events.setCommandHandler("config:contractsConfig:set", this.setConfig.bind(this, 'contractsConfig'));
this.events.setCommandHandler("config:blockchainConfig:set", this.setConfig.bind(this, 'blockchainConfig'));
this.events.setCommandHandler("config:storageConfig:set", this.setConfig.bind(this, 'storageConfig'));
this.events.setCommandHandler("config:namesystemConfig:set", this.setConfig.bind(this, 'namesystemConfig'));
this.events.setCommandHandler("config:communicationConfig:set", this.setConfig.bind(this, 'communicationConfig'));
this.events.setCommandHandler("config:contractsFiles", (cb) => {
cb(null, this.contractsFiles);
});
// TODO: refactor this so reading the file can be done with a normal resolver or something that takes advantage of the plugin api
this.events.setCommandHandler("config:contractsFiles:add", (filename, resolver) => {
resolver = resolver || function(callback) {
callback(fs.readFileSync(filename).toString());
};
this.contractsFiles.push(new File({path: filename, originalPath: filename, type: Types.custom, resolver}));
});
this.events.setCommandHandler("config:contractsFiles:reset", (cb) => {
this.contractsFiles.forEach((file) => {
if(file.path.includes(".embark")) {
fs.removeSync(file.path);
}
this.contractsFiles = this.contractsFiles.filter((contractFile) => contractFile.path !== file.path);
});
cb();
});
this.events.on('file-remove', (fileType, removedPath) => {
if(fileType !== 'contract') return;
const normalizedPath = path.normalize(removedPath);
this.contractsFiles = this.contractsFiles.filter(file => path.normalize(file.path) !== normalizedPath);
});
};
// TODO remove this at some point as it is now in plugin
Config.prototype.dappPath = dappPath;
Config.prototype.loadConfigFiles = function(options) {
var interceptLogs = options.interceptLogs;
if (options.interceptLogs === undefined) {
interceptLogs = true;
}
if (!fs.existsSync(options.embarkConfig)){
this.logger.error(__('Cannot find file %s Please ensure you are running this command inside the Dapp folder', options.embarkConfig));
process.exit(1);
}
this.embarkConfig = fs.readJSONSync(options.embarkConfig);
this.embarkConfig.plugins = this.embarkConfig.plugins || {};
this.plugins = new Plugins({
plugins: this.embarkConfig.plugins,
logger: this.logger,
interceptLogs: interceptLogs,
events: this.events,
config: this,
context: this.context,
env: this.env,
version: this.version
});
this.plugins.loadPlugins();
this.loadEmbarkConfigFile();
this.loadBlockchainConfigFile();
this.loadStorageConfigFile();
this.loadContractFiles();
this.loadCommunicationConfigFile();
this.loadNameSystemConfigFile();
this.loadPipelineConfigFile();
this.loadAssetFiles();
this.loadContractsConfigFile();
this.loadExternalContractsFiles();
this.loadWebServerConfigFile();
this.loadPluginContractFiles();
this._updateBlockchainCors();
};
Config.prototype.reloadConfig = function() {
this.loadEmbarkConfigFile();
this.loadBlockchainConfigFile();
this.loadStorageConfigFile();
this.loadContractFiles();
this.loadCommunicationConfigFile();
this.loadNameSystemConfigFile();
this.loadPipelineConfigFile();
this.loadAssetFiles();
this.loadContractsConfigFile();
this.loadExternalContractsFiles();
this._updateBlockchainCors();
};
Config.prototype.loadContractFiles = function() {
const loadedContractFiles = this.loadFiles(this.embarkConfig.contracts);
// `this.contractsFiles` could've been mutated at runtime using
// either `config:contractsFiles:add` event or through calls to
// `loadExternalContractsFiles()`, so we have to make sure we preserve
// those added files before we reset `this.contractsFiles`.
//
// We do that by determining the difference between `loadedContractFiles` and the ones
// already in memory in `this.contractsFiles`.
const addedContractFiles = this.contractsFiles.filter(existingFile => !loadedContractFiles.some(file => file.originalPath === existingFile.originalPath));
this.contractsFiles = loadedContractFiles.concat(addedContractFiles);
};
Config.prototype._updateBlockchainCors = function(){
let blockchainConfig = this.blockchainConfig;
let storageConfig = this.storageConfig;
let webServerConfig = this.webServerConfig;
let corsParts = cloneDeep(this.corsParts);
if (blockchainConfig.isDev) {
corsParts.push('*');
}
if(webServerConfig && webServerConfig.host) {
corsParts.push(buildUrlFromConfig(webServerConfig));
}
if(storageConfig && storageConfig.enabled) {
// if getUrl is specified in the config, that needs to be included in cors
// instead of the concatenated protocol://host:port
if(storageConfig.upload.getUrl) {
// remove /ipfs or /bzz: from getUrl if it's there
let getUrlParts = storageConfig.upload.getUrl.split('/');
getUrlParts = getUrlParts.slice(0, 3);
let host = canonicalHost(getUrlParts[2].split(':')[0]);
let port = getUrlParts[2].split(':')[1];
getUrlParts[2] = port ? [host, port].join(':') : host;
corsParts.push(getUrlParts.join('/'));
}
// use our modified getUrl or in case it wasn't specified, use a built url
else{
corsParts.push(buildUrlFromConfig(storageConfig.upload));
}
}
// Add cors for the proxy and whisper
corsParts.push(constants.embarkResourceOrigin);
corsParts = Array.from(new Set(corsParts));
this.corsParts = corsParts;
let cors = corsParts.join(',');
if (blockchainConfig.rpcCorsDomain === 'auto') {
blockchainConfig.rpcCorsDomain = cors;
} else if (typeof blockchainConfig.rpcCorsDomain === 'object') {
let tempCors = blockchainConfig.rpcCorsDomain.auto ? corsParts : [];
tempCors = tempCors.concat(blockchainConfig.rpcCorsDomain.additionalCors || []);
blockchainConfig.rpcCorsDomain = tempCors.join(',');
}
if (blockchainConfig.wsOrigins === 'auto') {
blockchainConfig.wsOrigins = cors;
} else if (typeof blockchainConfig.wsOrigins === 'object') {
let tempCors = blockchainConfig.wsOrigins.auto ? corsParts : [];
tempCors = tempCors.concat(blockchainConfig.wsOrigins.additionalCors || []);
blockchainConfig.wsOrigins = tempCors.join(',');
}
};
Config.prototype._loadConfigFile = function (configFilePath, defaultConfig, enabledByDefault) {
if (!configFilePath) {
const configToReturn = defaultConfig['default'] || {};
configToReturn.enabled = enabledByDefault || false;
return configToReturn;
}
configFilePath = configFilePath.replace('.json','').replace('.js', '');
let config;
if (fs.existsSync(configFilePath + '.js')) {
delete require.cache[configFilePath + '.js'];
config = require(configFilePath + '.js');
} else if (fs.existsSync(configFilePath + '.json')) {
config = fs.readJSONSync(configFilePath + '.json');
} else {
this.logger.warn(__("no config file found at %s using default config", configFilePath));
return defaultConfig['default'] || {};
}
return config;
};
Config.prototype._doMergeConfig = function(config, defaultConfig, env) {
let configObject = recursiveMerge(defaultConfig, config);
if (env) {
if (env === 'test' && !configObject[env]) {
// Disabled all configs in tests as they are opt in
return Object.assign({}, defaultConfig.default, {enabled: false});
}
return recursiveMerge(configObject.default || {}, configObject[env]);
} else if (env !== false) {
this.logger.info(__("No environment called %s found. Using defaults.", env));
}
return configObject;
};
Config.prototype._loadAndMergeConfig = function(configFilePath, defaultConfig, env, enabledByDefault) {
const config = this._loadConfigFile(configFilePath, defaultConfig, enabledByDefault);
return this._doMergeConfig(config, defaultConfig, env, enabledByDefault);
};
Config.prototype._getFileOrObject = function(object, filePath, property) {
if (typeof object === 'object') {
return object[property] ? dappPath(object[property]) : object[property];
}
return dappPath(object, filePath);
};
/*eslint complexity: ["error", 30]*/
Config.prototype.loadBlockchainConfigFile = function() {
const blockchainDefaults = getBlockchainDefaults(this.env);
const configFilePath = this._getFileOrObject(this.configDir, 'blockchain', 'blockchain');
const userConfig = this._loadConfigFile(configFilePath, blockchainDefaults, true);
const envConfig = userConfig[this.env];
if (envConfig) {
if (envConfig.ethereumClientName || envConfig.hasOwnProperty('isDev') || envConfig.hasOwnProperty('mineWhenNeeded')) {
this.logger.error(__('The blockchain config has changed quite a bit in Embark 5\nPlease visit %s to know what has to be changed', embark5ChangesUrl.underline));
process.exit(1);
}
if (envConfig.clientConfig) {
Object.assign(envConfig, envConfig.clientConfig);
delete envConfig.clientConfig;
}
switch (envConfig.miningMode) {
case 'dev': envConfig.isDev = true; break;
case 'auto': envConfig.isDev = false; envConfig.mineWhenNeeded = true; break;
case 'always': envConfig.isDev = false; envConfig.mineWhenNeeded = false; envConfig.mine = true; break;
case 'off': envConfig.isDev = false; envConfig.mineWhenNeeded = false; envConfig.mine = false; break;
default: envConfig.isDev = false;
}
if (envConfig.cors) {
const autoIndex = envConfig.cors.indexOf('auto');
envConfig.rpcCorsDomain = {};
envConfig.wsOrigins = {};
if (autoIndex > -1) {
envConfig.rpcCorsDomain.auto = true;
envConfig.wsOrigins.auto = true;
envConfig.cors.splice(autoIndex, 1);
} else {
envConfig.rpcCorsDomain.auto = false;
envConfig.wsOrigins.auto = false;
}
envConfig.rpcCorsDomain.additionalCors = envConfig.cors;
envConfig.wsOrigins.additionalCors = envConfig.cors;
delete envConfig.cors;
}
userConfig[this.env] = envConfig;
}
this.blockchainConfig = this._doMergeConfig(userConfig, blockchainDefaults, this.env);
if (!configFilePath) {
this.blockchainConfig.default = true;
}
if (this.blockchainConfig.targetGasLimit && this.blockchainConfig.targetGasLimit.toString().match(unitRegex)) {
this.blockchainConfig.targetGasLimit = getWeiBalanceFromString(this.blockchainConfig.targetGasLimit, web3);
}
if (this.blockchainConfig.gasPrice && this.blockchainConfig.gasPrice.toString().match(unitRegex)) {
this.blockchainConfig.gasPrice = getWeiBalanceFromString(this.blockchainConfig.gasPrice, web3);
}
if (this.blockchainConfig.accounts) {
this.blockchainConfig.accounts.forEach(acc => {
if (acc.balance && acc.balance.toString().match(unitRegex)) {
acc.balance = getWeiBalanceFromString(acc.balance, web3);
}
});
}
if (!this.blockchainConfig.endpoint) {
const urlConfig = (this.blockchainConfig.wsHost) ? {
host: this.blockchainConfig.wsHost,
port: this.blockchainConfig.wsPort,
type: 'ws'
} : {
host: this.blockchainConfig.rpcHost,
port: this.blockchainConfig.rpcPort,
type: 'rpc'
};
this.blockchainConfig.endpoint = buildUrlFromConfig(urlConfig);
this.blockchainConfig.isAutoEndpoint = true;
}
if (
!this.shownNoAccountConfigMsg &&
(/rinkeby|testnet|livenet/).test(this.blockchainConfig.networkType) &&
!(this.blockchainConfig.accounts && this.blockchainConfig.accounts.find(acc => acc.password)) &&
!this.blockchainConfig.isDev &&
this.env !== 'development' && this.env !== 'test') {
this.logger.warn((
'\n=== ' + __('Cannot unlock account - account config missing').bold + ' ===\n' +
__('Geth is configured to sync to a testnet/livenet and needs to unlock an account ' +
'to allow your dApp to interact with geth, however, the address and password must ' +
'be specified in your blockchain config. Please update your blockchain config with ' +
'a valid address and password: \n') +
` - config/blockchain.js > ${this.env} > account\n\n`.italic +
__('Please also make sure the keystore file for the account is located at: ') +
'\n - Mac: ' + `~/Library/Ethereum/${this.env}/keystore`.italic +
'\n - Linux: ' + `~/.ethereum/${this.env}/keystore`.italic +
'\n - Windows: ' + `%APPDATA%\\Ethereum\\${this.env}\\keystore`.italic) +
__('\n\nAlternatively, you could change ' +
`config/blockchain.js > ${this.env} > networkType`.italic +
__(' to ') +
'"custom"\n'.italic).yellow
);
this.shownNoAccountConfigMsg = true;
}
const accountDocsMessage = __('For more info, check the docs: %s', 'https://embark.status.im/docs/blockchain_accounts_configuration.html'.underline);
if (this.blockchainConfig.account) {
this.logger.error(__('The `account` config for the blockchain was removed. Please use `accounts` instead.'));
this.logger.error(accountDocsMessage);
process.exit(1);
}
if (this.blockchainConfig.simulatorMnemonic) {
this.logger.error(__('The `simulatorMnemonic` config for the blockchain was removed. Please use `accounts` instead.'));
this.logger.error(accountDocsMessage);
process.exit(1);
}
this.events.emit('config:load:blockchain', this.blockchainConfig);
};
Config.prototype.loadContractsConfigFile = function() {
let configObject = getContractDefaults(this.embarkConfig.versions);
const contractsConfigs = this.plugins.getPluginsProperty('contractsConfig', 'contractsConfigs');
contractsConfigs.forEach(function(pluginConfig) {
configObject = recursiveMerge(configObject, pluginConfig);
});
let configFilePath = this._getFileOrObject(this.configDir, 'contracts', 'contracts');
let newContractsConfig = this._loadAndMergeConfig(configFilePath, configObject, this.env);
if (newContractsConfig.contracts) {
this.logger.error(__('`contracts` has been renamed `deploy` in contracts config\nFor more information: %s', embark5ChangesUrl.underline));
process.exit(1);
}
if (newContractsConfig.deployment) {
this.logger.error(__('`deployment` has been removed from contracts config and is now part of blockchain config\nFor more information: %s', embark5ChangesUrl.underline));
process.exit(1);
}
if (newContractsConfig.gas.match(unitRegex)) {
newContractsConfig.gas = getWeiBalanceFromString(newContractsConfig.gas, web3);
}
newContractsConfig = prepareContractsConfig(newContractsConfig);
const afterDeploy = newContractsConfig.afterDeploy;
if (Array.isArray(afterDeploy)) {
newContractsConfig.afterDeploy = afterDeploy.map(replaceZeroAddressShorthand);
}
if (!deepEqual(newContractsConfig, this.contractsConfig)) {
this.contractsConfig = newContractsConfig;
}
this.events.emit('config:load:contracts', this.contractsConfig);
};
Config.prototype.loadExternalContractsFiles = function() {
let contracts = this.contractsConfig.contracts;
let storageConfig = this.storageConfig;
if (storageConfig && storageConfig.upload && storageConfig.upload.getUrl) {
this.providerUrl = storageConfig.upload.getUrl;
}
for (let contractName in contracts) {
let contract = contracts[contractName];
if (!contract.file) {
continue;
}
let externalContractFile = null;
if (contract.file.startsWith('http') || contract.file.startsWith('git') || contract.file.startsWith('ipfs') || contract.file.startsWith('bzz')) {
const fileObj = getExternalContractUrl(contract.file, this.providerUrl);
if (!fileObj) {
return this.logger.error(__("HTTP contract file not found") + ": " + contract.file);
}
externalContractFile = new File({ path: fileObj.filePath, originalPath: fileObj.filePath, type: Types.http, basedir: '', externalUrl: fileObj.url, storageConfig });
} else if (fs.existsSync(contract.file)) {
externalContractFile = new File({ path: contract.file, originalPath: contract.file, type: Types.dappFile, basedir: '', storageConfig });
} else if (fs.existsSync(path.join('./node_modules/', contract.file))) {
const completePath = path.join('./node_modules/', contract.file);
externalContractFile = new File({ path: completePath, originalPath: completePath, type: Types.dappFile, basedir: '', storageConfig });
}
if (externalContractFile) {
const index = this.contractsFiles.findIndex(contractFile => contractFile.originalPath === externalContractFile.originalPath);
// It's important that we only add `externalContractFile` if it doesn't exist already
// within `contractsFiles`, otherwise we keep adding duplicates in subsequent
// compilation routines creating a memory leak.
if (index > -1) {
this.contractsFiles[index] = externalContractFile;
} else {
this.contractsFiles.push(externalContractFile);
}
} else {
this.logger.error(__("contract file not found") + ": " + contract.file);
}
}
};
Config.prototype.loadStorageConfigFile = function() {
var versions = recursiveMerge({"ipfs-api": "17.2.4"}, this.embarkConfig.versions || {});
var configObject = {
"default": {
"versions": versions,
"enabled": true,
"available_providers": ["ipfs", "swarm"],
"ipfs_bin": "ipfs",
"upload": {
"provider": "ipfs",
"protocol": "http",
"host" : defaultHost,
"port": 5001,
"getUrl": "http://localhost:8080/ipfs/"
},
"dappConnection": [{"provider": "ipfs", "host": "localhost", "port": 5001, "getUrl": "http://localhost:8080/ipfs/"}]
}
};
let configFilePath = this._getFileOrObject(this.configDir, 'storage', 'storage');
this.storageConfig = this._loadAndMergeConfig(configFilePath, configObject, this.env);
this.events.emit('config:load:storage', this.storageConfig);
};
Config.prototype.loadNameSystemConfigFile = function() {
// todo: spec out names for registration in the file itself for a dev chain
var configObject = {
"default": {
"enabled": false
}
};
let configFilePath = this._getFileOrObject(this.configDir, 'namesystem', 'namesystem');
this.namesystemConfig = this._loadAndMergeConfig(configFilePath, configObject, this.env);
};
Config.prototype.loadCommunicationConfigFile = function() {
var configObject = {
"default": {
"enabled": true,
"provider": "whisper",
"available_providers": ["whisper"],
"connection": {
"host": defaultHost,
"port": 8557,
"type": "ws"
}
}
};
let configFilePath = this._getFileOrObject(this.configDir, 'communication', 'communication');
this.communicationConfig = this._loadAndMergeConfig(configFilePath, configObject, this.env);
this.events.emit('config:load:communication', this.communicationConfig);
};
Config.prototype.loadWebServerConfigFile = function() {
var configObject = {
"enabled": true,
"host": defaultHost,
"openBrowser": true,
"port": 8000,
"enableCatchAll": true,
"protocol": "http"
};
let configFilePath = this._getFileOrObject(this.configDir, 'webserver', 'webserver');
let webServerConfig = this._loadAndMergeConfig(configFilePath, configObject, false);
if (webServerConfig.https){
try {
webServerConfig.certOptions = {
key: fs.readFileSync(webServerConfig.key),
cert: fs.readFileSync(webServerConfig.cert)
};
webServerConfig.protocol = 'https';
} catch (e) {
this.logger.error(e.message);
this.logger.warn('Invalid path for key/cert in config/webserver.js. Using http instead.');
webServerConfig.certOptions = {};
webServerConfig.protocol = 'http';
}
}
if (configFilePath === false) {
this.webServerConfig = {enabled: false};
return;
}
if (this.webServerConfig) {
// cli flags to `embark run` should override configFile and defaults (configObject)
this.webServerConfig = recursiveMerge(webServerConfig, this.webServerConfig);
} else {
this.webServerConfig = webServerConfig;
}
if (!this.pipelineConfig.enabled) {
this.webServerConfig.enabled = false;
}
this.events.emit('config:load:webserver', this.webServerConfig);
};
Config.prototype.loadEmbarkConfigFile = function() {
var configObject = {
options: {
solc: {
"optimize": true,
"optimize-runs": 200
}
},
"generationDir": "embarkArtifacts"
};
this.embarkConfig = recursiveMerge(configObject, this.embarkConfig);
const contracts = this.embarkConfig.contracts;
// determine contract 'root' directories
this.contractDirectories = contracts.map((dir) => {
return dir.split("**")[0];
}).map((dir) => {
return dir.split("*.")[0];
});
this.contractDirectories.push(constants.httpContractsDirectory);
this.buildDir = this.embarkConfig.buildDir;
this.configDir = this.embarkConfig.config;
};
Config.prototype.loadPipelineConfigFile = function() {
const defaultPipelineConfig = {
typescript: false,
enabled: true
};
let pipelineConfigPath = this._getFileOrObject(this.configDir, 'pipeline', 'pipeline');
// Embark applications in "simple" mode that aren't aware of `pipeline.js` configuration capabilities
// won't have a pipeline config path so we need to perform this safety check here, otherwise the
// next expression is going to throw.
if (pipelineConfigPath !== undefined) {
// At this point, `pipelineConfigPath` could be either `config/pipeline` or a filepath including its extension.
// We need to make sure that we always have an extension.
pipelineConfigPath = `${dappPath(pipelineConfigPath)}${path.extname(pipelineConfigPath) === '.js' ? '' : '.js'}`;
}
let pipelineConfig = defaultPipelineConfig;
if (pipelineConfigPath && fs.existsSync(pipelineConfigPath)) {
delete require.cache[pipelineConfigPath];
pipelineConfig = recursiveMerge(
recursiveMerge(true, pipelineConfig),
require(pipelineConfigPath)
);
}
this.pipelineConfig = pipelineConfig;
this.events.emit('config:load:pipeline', this.pipelineConfig);
};
Config.prototype.loadAssetFiles = function () {
if(!this.embarkConfig.app) return;
Object.keys(this.embarkConfig.app).forEach(targetFile => {
this.assetFiles[targetFile] = this.loadFiles(this.embarkConfig.app[targetFile]);
});
};
function findMatchingExpression(filename, filesExpressions) {
for (let fileExpression of filesExpressions) {
var matchingFiles = utils.filesMatchingPattern(fileExpression);
for (let matchFile of matchingFiles) {
if (matchFile === filename) {
return path.dirname(fileExpression).replace(/\*/g, '');
}
}
}
return path.dirname(filename);
}
Config.prototype.loadFiles = function(files) {
var self = this;
var originalFiles = utils.filesMatchingPattern(files);
var readFiles = [];
let storageConfig = self.storageConfig;
originalFiles.filter(function(file) {
return (file[0] === '$' || file.indexOf('.') >= 0);
}).filter(function(file) {
let basedir = findMatchingExpression(file, files);
readFiles.push(new File({path: file, originalPath: file, type: Types.dappFile, basedir: basedir, storageConfig: storageConfig}));
});
var filesFromPlugins = [];
var filePlugins = self.plugins.getPluginsFor('pipelineFiles');
filePlugins.forEach(function(plugin) {
try {
var fileObjects = plugin.runFilePipeline();
for (var i=0; i < fileObjects.length; i++) {
var fileObject = fileObjects[i];
filesFromPlugins.push(fileObject);
}
}
catch(err) {
self.logger.error(err.message);
}
});
filesFromPlugins.filter(function(file) {
if ((file.intendedPath && utils.fileMatchesPattern(files, file.intendedPath)) || utils.fileMatchesPattern(files, file.file)) {
readFiles.push(file);
}
});
return readFiles;
};
// NOTE: this doesn't work for internal modules
Config.prototype.loadPluginContractFiles = function() {
var self = this;
let storageConfig = self.storageConfig;
var contractsPlugins = this.plugins.getPluginsFor('contractFiles');
contractsPlugins.forEach(function(plugin) {
plugin.contractsFiles.forEach(function(file) {
var filename = file.replace('./','');
self.contractsFiles.push(new File({ path: filename, originalPath: path.join(plugin.pluginPath, filename), pluginPath: plugin.pluginPath, type: Types.custom, storageConfig,
resolver: function(callback) {
callback(plugin.loadPluginFile(file));
}
}));
});
});
};
module.exports = Config;

View File

@ -1,127 +0,0 @@
/* global module process require */
const fs = require('fs-extra');
const parseJson = require('parse-json');
const path = require('path');
import { joinPath } from 'embark-utils';
import './env';
require('colors');
function mkdirpSync(...args) { return fs.mkdirpSync(...args); }
function mkdirp(...args) { return fs.mkdirp(...args); }
function readdir(...args) { return fs.readdir(...args); }
function stat(...args) { return fs.stat(...args); }
function remove(...args) { return fs.remove(...args); }
function copy(...args) { return fs.copy(...args); }
function copySync(...args) { return fs.copySync(...args); }
function move(...args) { return fs.move(...args); }
function moveSync(...args) { return fs.moveSync(...args); }
function symlink(...args) { return fs.symlink(...args); }
function appendFileSync(...args) { return fs.appendFileSync(...args); }
function writeFile(...args) { return fs.writeFile(...args); }
function writeFileSync(...args) { return fs.writeFileSync(...args); }
function readFile(...args) { return fs.readFile(...args); }
function readFileSync(...args) { return fs.readFileSync(...args); }
function readdirSync(...args) { return fs.readdirSync(...args); }
function statSync(...args) { return fs.statSync(...args); }
function readJSONSync(...args) {
let json;
try {
json = parseJson(readFileSync(...args));
} catch (e) {
console.error('error: '.red + args[0].green.underline + ' ' + e.message.green);
process.exit(1);
}
return json;
}
function writeJSONSync(...args) { return fs.writeJSONSync(...args); }
function outputJSONSync(...args) { return fs.outputJSONSync(...args); }
function writeJson(...args) { return fs.writeJson(...args); }
function existsSync(...args) { return fs.existsSync(...args); }
function ensureFileSync(...args) { return fs.ensureFileSync(...args); }
function ensureDirSync(...args) { return fs.ensureDirSync(...args); }
function access(...args) { return fs.access(...args); }
function removeSync(...args) { return fs.removeSync(...args); }
function createWriteStream(...args) { return fs.createWriteStream(...args); }
function copyPreserve(sourceFilePath, targetFilePath) {
const implementation = (sourceFilePath, targetFilePath) => {
let ext = 1;
let preserved = targetFilePath;
while (fs.existsSync(preserved)) {
const extname = path.extname(targetFilePath);
preserved = joinPath(
path.dirname(targetFilePath),
`${path.basename(targetFilePath, extname)}.${ext}${extname}`
);
ext++;
}
if (preserved !== targetFilePath) {
fs.copySync(targetFilePath, preserved);
}
fs.copySync(sourceFilePath, targetFilePath);
};
return implementation(sourceFilePath, targetFilePath);
}
function outputFileSync(...args) { return fs.outputFileSync(...args); }
module.exports = {
access,
appendFileSync,
copy,
copyPreserve,
copySync,
createWriteStream,
existsSync,
ensureFileSync,
ensureDirSync,
mkdirp,
mkdirpSync,
move,
moveSync,
outputFileSync,
outputJSONSync,
readFile,
readFileSync,
readJSONSync,
readdir,
readdirSync,
remove,
removeSync,
stat,
statSync,
symlink,
writeFile,
writeFileSync,
writeJSONSync,
writeJson
};

View File

@ -1,303 +0,0 @@
const utils = require('../utils/utils.js');
import { __ } from 'embark-i18n';
import { dappPath, embarkPath, isEs6Module, joinPath } from 'embark-utils';
const constants = require('embark-core/constants');
const fs = require('fs-extra');
const deepEqual = require('deep-equal');
// TODO: pass other params like blockchainConfig, contract files, etc..
var Plugin = function(options) {
this.name = options.name;
this.isInternal = options.isInternal;
this.pluginModule = options.pluginModule;
this.pluginPath = options.pluginPath;
this.pluginConfig = options.pluginConfig;
this.shouldInterceptLogs = options.interceptLogs;
this.clientWeb3Providers = [];
this.beforeDeploy = [];
this.contractsGenerators = [];
this.generateCustomContractCode = null;
this.testContractFactory = null;
this.pipeline = [];
this.pipelineFiles = [];
this.console = [];
this.contractsConfigs = [];
this.contractsFiles = [];
this.compilers = [];
this.serviceChecks = [];
this.dappGenerators = [];
this.pluginTypes = [];
this.uploadCmds = [];
this.apiCalls = [];
this.imports = [];
this.embarkjs_code = [];
this.generated_code = [];
this.embarkjs_init_code = {};
this.embarkjs_init_console_code = {};
this.fs = fs;
this.afterContractsDeployActions = [];
this.onDeployActions = [];
this.eventActions = {};
this._loggerObject = options.logger;
this.logger = this._loggerObject; // Might get changed if we do intercept
this.events = options.events;
this.config = options.config;
this.plugins = options.plugins;
this.env = options.env;
this.loaded = false;
this.currentContext = options.context;
this.acceptedContext = options.pluginConfig.context || [constants.contexts.any];
this.version = options.version;
this.constants = constants;
if (!Array.isArray(this.currentContext)) {
this.currentContext = [this.currentContext];
}
if (!Array.isArray(this.acceptedContext)) {
this.acceptedContext = [this.acceptedContext];
}
};
Plugin.prototype.dappPath = dappPath;
Plugin.prototype.embarkPath = embarkPath;
Plugin.prototype._log = function(type) {
this._loggerObject[type](this.name + ':', ...[].slice.call(arguments, 1));
};
Plugin.prototype.setUpLogger = function () {
this.logger = {
log: this._log.bind(this, 'log'),
warn: this._log.bind(this, 'warn'),
error: this._log.bind(this, 'error'),
info: this._log.bind(this, 'info'),
debug: this._log.bind(this, 'debug'),
trace: this._log.bind(this, 'trace'),
dir: this._log.bind(this, 'dir')
};
};
Plugin.prototype.isContextValid = function() {
if (this.currentContext.includes(constants.contexts.any) || this.acceptedContext.includes(constants.contexts.any)) {
return true;
}
return this.acceptedContext.some(context => {
return this.currentContext.includes(context);
});
};
Plugin.prototype.hasContext = function(context) {
return this.currentContext.includes(context);
};
Plugin.prototype.loadPlugin = function() {
if (!this.isContextValid()) {
this.logger.warn(__('Plugin {{name}} can only be loaded in the context of "{{contexts}}"', {name: this.name, contexts: this.acceptedContext.join(', ')}));
return false;
}
this.loaded = true;
if (this.shouldInterceptLogs) {
this.setUpLogger();
}
if (isEs6Module(this.pluginModule)) {
if (this.pluginModule.default) {
this.pluginModule = this.pluginModule.default;
}
return new this.pluginModule(this);
}
this.pluginModule.call(this, this);
};
Plugin.prototype.loadInternalPlugin = function() {
if (isEs6Module(this.pluginModule)) {
if (this.pluginModule.default) {
this.pluginModule = this.pluginModule.default;
}
}
return new this.pluginModule(this, this.pluginConfig); /*eslint no-new: "off"*/
};
Plugin.prototype.loadPluginFile = function(filename) {
return fs.readFileSync(this.pathToFile(filename)).toString();
};
Plugin.prototype.pathToFile = function(filename) {
if (!this.pluginPath) {
throw new Error('pluginPath not defined for plugin: ' + this.name);
}
return joinPath(this.pluginPath, filename);
};
// TODO: add deploy provider
Plugin.prototype.registerClientWeb3Provider = function(cb) {
this.clientWeb3Providers.push(cb);
this.addPluginType('clientWeb3Provider');
};
Plugin.prototype.registerContractsGeneration = function(cb) {
this.contractsGenerators.push(cb);
this.addPluginType('contractGeneration');
};
Plugin.prototype.registerCustomContractGenerator = function (cb) {
this.generateCustomContractCode = cb;
this.addPluginType('customContractGeneration');
};
Plugin.prototype.registerTestContractFactory = function(cb) {
this.testContractFactory = cb;
this.addPluginType('testContractFactory');
};
Plugin.prototype.registerPipeline = function(matcthingFiles, cb) {
// TODO: generate error for more than one pipeline per plugin
this.pipeline.push({matcthingFiles: matcthingFiles, cb: cb});
this.addPluginType('pipeline');
};
Plugin.prototype.registerDappGenerator = function(framework, cb){
this.dappGenerators.push({framework: framework, cb: cb});
this.pluginTypes.push('dappGenerator');
};
Plugin.prototype.registerCustomType = function(type){
this.pluginTypes.push(type);
};
Plugin.prototype.addFileToPipeline = function(file, intendedPath, options) {
this.pipelineFiles.push({file: file, intendedPath: intendedPath, options: options});
this.addPluginType('pipelineFiles');
};
Plugin.prototype.addContractFile = function(file) {
if (this.isInternal) {
throw new Error("this API cannot work for internal modules. please use an event command instead: config:contractsFiles:add");
}
this.contractsFiles.push(file);
this.addPluginType('contractFiles');
};
Plugin.prototype.registerConsoleCommand = function(optionsOrCb) {
if (typeof optionsOrCb === 'function') {
this.logger.warn(__('Registering console commands with function syntax is deprecated and will likely be removed in future versions of Embark'));
this.logger.info(__('You can find the new API documentation here: %s', 'https://embark.status.im/docs/plugin_reference.html#registerConsoleCommand-options'.underline));
}
this.console.push(optionsOrCb);
this.addPluginType('console');
};
// TODO: this only works for services done on startup
Plugin.prototype.registerServiceCheck = function(checkName, checkFn, time) {
this.serviceChecks.push({checkName: checkName, checkFn: checkFn, time: time});
this.addPluginType('serviceChecks');
};
Plugin.prototype.has = function(pluginType) {
return this.pluginTypes.indexOf(pluginType) >= 0;
};
Plugin.prototype.addPluginType = function(pluginType) {
this.pluginTypes.push(pluginType);
this.pluginTypes = Array.from(new Set(this.pluginTypes));
};
Plugin.prototype.generateProvider = function(args) {
return this.clientWeb3Providers.map(function(cb) {
return cb.call(this, args);
}).join("\n");
};
Plugin.prototype.generateContracts = function(args) {
return this.contractsGenerators.map(function(cb) {
return cb.call(this, args);
}).join("\n");
};
Plugin.prototype.registerContractConfiguration = function(config) {
this.contractsConfigs.push(config);
this.addPluginType('contractsConfig');
};
Plugin.prototype.registerCompiler = function(extension, cb) {
this.compilers.push({extension: extension, cb: cb});
this.addPluginType('compilers');
};
Plugin.prototype.registerUploadCommand = function(cmd, cb) {
this.uploadCmds.push({cmd: cmd, cb: cb});
this.addPluginType('uploadCmds');
};
Plugin.prototype.addCodeToEmbarkJS = function(code) {
this.addPluginType('embarkjsCode');
// TODO: what is this/why
if (!this.embarkjs_code.some((existingCode) => deepEqual(existingCode, code))) {
this.embarkjs_code.push(code);
}
};
Plugin.prototype.addGeneratedCode = function(codeCb) {
this.addPluginType('generatedCode');
this.generated_code.push(codeCb);
};
Plugin.prototype.addProviderInit = function(providerType, code, initCondition) {
this.embarkjs_init_code[providerType] = this.embarkjs_init_code[providerType] || [];
this.embarkjs_init_code[providerType].push([code, initCondition]);
this.addPluginType('initCode');
};
Plugin.prototype.addConsoleProviderInit = function(providerType, code, initCondition) {
this.embarkjs_init_console_code[providerType] = this.embarkjs_init_console_code[providerType] || [];
this.addPluginType('initConsoleCode');
const toAdd = [code, initCondition];
if (!this.embarkjs_init_console_code[providerType].some((initConsoleCode) => deepEqual(initConsoleCode, toAdd))) {
this.embarkjs_init_console_code[providerType].push(toAdd);
}
};
Plugin.prototype.registerImportFile = function(importName, importLocation) {
this.imports.push([importName, importLocation]);
this.addPluginType('imports');
};
Plugin.prototype.registerActionForEvent = function(eventName, cb) {
if (!this.eventActions[eventName]) {
this.eventActions[eventName] = [];
}
this.eventActions[eventName].push(cb);
this.addPluginType('eventActions');
};
Plugin.prototype.registerAPICall = function(method, endpoint, cb) {
this.apiCalls.push({method, endpoint, cb});
this.addPluginType('apiCalls');
this.events.emit('plugins:register:api', {method, endpoint, cb});
};
Plugin.prototype.runFilePipeline = function() {
var self = this;
return this.pipelineFiles.map(function(file) {
var obj = {};
obj.filename = file.file.replace('./','');
obj.content = self.loadPluginFile(file.file).toString();
obj.intendedPath = file.intendedPath;
obj.options = file.options;
obj.path = self.pathToFile(obj.filename);
return obj;
});
};
Plugin.prototype.runPipeline = function(args) {
// TODO: should iterate the pipelines
var pipeline = this.pipeline[0];
var shouldRunPipeline = utils.fileMatchesPattern(pipeline.matcthingFiles, args.targetFile);
if (shouldRunPipeline) {
return pipeline.cb.call(this, args);
}
return args.source;
};
module.exports = Plugin;

View File

@ -1,249 +0,0 @@
import { dappPath, embarkPath } from 'embark-utils';
const async = require('async');
var Plugin = require('./plugin.js');
var fs = require('../core/fs.js');
var Plugins = function(options) {
this.pluginList = options.plugins || [];
this.interceptLogs = options.interceptLogs;
this.plugins = [];
// TODO: need backup 'NullLogger'
this.logger = options.logger;
this.events = options.events;
this.config = options.config;
this.context = options.context;
this.fs = fs;
this.env = options.env;
this.version = options.version;
};
Plugins.deprecated = {
'embarkjs-connector-web3': '4.1.0'
};
Plugins.prototype.loadPlugins = function() {
Object.entries(Plugins.deprecated).forEach(([pluginName, embarkVersion]) => {
if (this.pluginList[pluginName]) {
delete this.pluginList[pluginName];
this.logger.warn(`${pluginName} plugin was not loaded because it has been deprecated as of embark v${embarkVersion}, please remove it from this project's embark.json and package.json`);
}
});
Object.entries(this.pluginList).forEach(([pluginName, pluginConfig]) => {
this.loadPlugin(pluginName, pluginConfig);
});
};
Plugins.prototype.listPlugins = function() {
return this.plugins.reduce((list, plugin) => {
if (plugin.loaded) {
list.push(plugin.name);
}
return list;
}, []);
};
// for services that act as a plugin but have core functionality
Plugins.prototype.createPlugin = function(pluginName, pluginConfig) {
let plugin = {};
let pluginPath = false;
var pluginWrapper = new Plugin({
name: pluginName,
pluginModule: plugin,
pluginConfig: pluginConfig,
logger: this.logger,
pluginPath: pluginPath,
interceptLogs: this.interceptLogs,
events: this.events,
config: this.config,
plugins: this.plugins,
fs: this.fs,
isInternal: true,
context: this.context
});
this.plugins.push(pluginWrapper);
return pluginWrapper;
};
Plugins.prototype.loadInternalPlugin = function(pluginName, pluginConfig, isPackage) {
let pluginPath, plugin;
if (isPackage) {
pluginPath = pluginName;
plugin = require(pluginName);
} else {
pluginPath = embarkPath('dist/lib/modules/' + pluginName);
plugin = require(pluginPath);
}
if (plugin.default) {
plugin = plugin.default;
}
const pluginWrapper = new Plugin({
name: pluginName,
pluginModule: plugin,
pluginConfig: pluginConfig || {},
logger: this.logger,
pluginPath: pluginPath,
interceptLogs: this.interceptLogs,
events: this.events,
config: this.config,
plugins: this.plugins,
fs: this.fs,
isInternal: true,
context: this.context,
env: this.env
});
const pluginInstance = pluginWrapper.loadInternalPlugin();
this.plugins.push(pluginWrapper);
return pluginInstance;
};
Plugins.prototype.loadPlugin = function(pluginName, pluginConfig) {
let pluginPath = dappPath('node_modules', pluginName);
let plugin = require(pluginPath);
if (plugin.default) {
plugin = plugin.default;
}
var pluginWrapper = new Plugin({
name: pluginName,
pluginModule: plugin,
pluginConfig: pluginConfig,
logger: this.logger,
pluginPath: pluginPath,
interceptLogs: this.interceptLogs,
events: this.events,
config: this.config,
plugins: this.plugins,
fs: this.fs,
isInternal: false,
context: this.context,
version: this.version
});
pluginWrapper.loadPlugin();
this.plugins.push(pluginWrapper);
};
Plugins.prototype.getPluginsFor = function(pluginType) {
return this.plugins.filter(function(plugin) {
return plugin.has(pluginType);
});
};
Plugins.prototype.getPluginsProperty = function(pluginType, property, sub_property) {
let matchingPlugins = this.plugins.filter(function(plugin) {
return plugin.has(pluginType);
});
// Sort internal plugins first
matchingPlugins.sort((a, b) => {
if (a.isInternal) {
return -1;
}
if (b.isInternal) {
return 1;
}
return 0;
});
let matchingProperties = matchingPlugins.map((plugin) => {
if (sub_property) {
return plugin[property][sub_property];
}
return plugin[property];
});
// Remove empty properties
matchingProperties = matchingProperties.filter((property) => property);
//return flattened list
if (matchingProperties.length === 0) return [];
return matchingProperties.reduce((a,b) => { return a.concat(b); }) || [];
};
Plugins.prototype.getPluginsPropertyAndPluginName = function(pluginType, property, sub_property) {
let matchingPlugins = this.plugins.filter(function(plugin) {
return plugin.has(pluginType);
});
// Sort internal plugins first
matchingPlugins.sort((a, b) => {
if (a.isInternal) {
return -1;
}
if (b.isInternal) {
return 1;
}
return 0;
});
let matchingProperties = [];
matchingPlugins.map((plugin) => {
if (sub_property) {
let newList = [];
for (let kall of (plugin[property][sub_property] || [])) {
matchingProperties.push([kall, plugin.name]);
}
return newList;
}
let newList = [];
for (let kall of (plugin[property] || [])) {
matchingProperties.push([kall, plugin.name]);
}
return newList;
});
// Remove empty properties
matchingProperties = matchingProperties.filter((property) => property[0]);
//return flattened list
if (matchingProperties.length === 0) return [];
// return matchingProperties.reduce((a,b) => { return a.concat(b); }) || [];
return matchingProperties;
};
// TODO: because this is potentially hanging, we should issue a trace warning if the event does not exists
Plugins.prototype.runActionsForEvent = function(eventName, args, cb) {
const self = this;
if (typeof (args) === 'function') {
cb = args;
args = [];
}
let actionPlugins = this.getPluginsPropertyAndPluginName('eventActions', 'eventActions', eventName);
if (actionPlugins.length === 0) {
return cb(null, args);
}
this.events.log("ACTION", eventName, "");
async.reduce(actionPlugins, args, function (current_args, pluginObj, nextEach) {
const [plugin, pluginName] = pluginObj;
self.events.log("== ACTION FOR " + eventName, plugin.name, pluginName);
if (typeof (args) === 'function') {
plugin.call(plugin, (...params) => {
nextEach(...params || current_args);
});
} else {
plugin.call(plugin, args, (...params) => {
nextEach(...params || current_args);
});
}
}, cb);
};
Plugins.prototype.emitAndRunActionsForEvent = function(eventName, args, cb) {
if (typeof (args) === 'function') {
cb = args;
args = [];
}
this.events.emit(eventName, args);
return this.runActionsForEvent(eventName, args, cb);
};
module.exports = Plugins;

View File

@ -1,92 +0,0 @@
import { __ } from 'embark-i18n';
class ServicesMonitor {
constructor(options) {
const self = this;
this.events = options.events;
this.logger = options.logger;
this.plugins = options.plugins;
this.checkList = {};
this.checkTimers = {};
this.checkState = {};
this.working = false;
self.events.setCommandHandler("services:register", (checkName, checkFn, time, initialStatus) => {
self.addCheck(checkName, checkFn, time, initialStatus);
});
}
}
ServicesMonitor.prototype.initCheck = function (checkName) {
let self = this;
let check = this.checkList[checkName];
if (!check) {
return false;
}
self.events.on('check:' + checkName, function (obj) {
if (check && check.status === 'off' && obj.status === 'on') {
self.events.emit('check:backOnline:' + checkName);
}
if (check && check.status === 'on' && obj.status === 'off') {
self.events.emit('check:wentOffline:' + checkName);
}
check.status = obj.status;
// const newState = {name: obj.name, status: obj.status, serviceName: checkName};
// if (!deepEqual(newState, self.checkState[checkName])) {
self.checkState[checkName] = {name: obj.name, status: obj.status, serviceName: checkName};
self.events.emit("servicesState", self.checkState);
// }
});
if (check.interval !== 0) {
self.checkTimers[checkName] = setInterval(function () {
check.fn.call(check.fn, function (obj) {
self.events.emit('check:' + checkName, obj);
});
}, check.interval);
}
check.fn.call(check.fn, function (obj) {
self.events.emit('check:' + checkName, obj);
});
};
ServicesMonitor.prototype.addCheck = function (checkName, checkFn, time, initialState) {
this.logger.trace('add check: ' + checkName);
this.checkList[checkName] = {fn: checkFn, interval: time || 5000, status: initialState};
if (this.working) {
this.initCheck(checkName);
}
};
ServicesMonitor.prototype.stopCheck = function (name) {
clearInterval(this.checkTimers[name]);
delete this.checkTimers[name];
delete this.checkList[name];
delete this.checkState[name];
};
ServicesMonitor.prototype.startMonitor = function () {
let self = this;
this.working = true;
this.logger.trace('startMonitor');
let servicePlugins = this.plugins.getPluginsProperty('serviceChecks', 'serviceChecks');
servicePlugins.forEach(function (pluginCheck) {
self.addCheck(pluginCheck.checkName, pluginCheck.checkFn, pluginCheck.time);
});
Object.keys(this.checkList).forEach(checkName => {
try {
self.initCheck(checkName);
} catch (err) {
self.logger.error(__("error running service check"));
self.logger.error(err.message);
}
});
};
module.exports = ServicesMonitor;

View File

@ -1,21 +1,26 @@
let version = require('../../package.json').version; let pkg = require('../../package.json');
const Logger = require('embark-logger'); import { Config, Events } from 'embark-core';
import { Logger } from 'embark-logger';
class Embark { class Embark {
constructor(options) { constructor(options) {
this.version = version; this.version = pkg.version;
this.options = options || {}; this.options = options || {};
} }
initConfig(env, options) { initConfig(env, options) {
let Events = require('./core/events.js');
let Config = require('./core/config.js');
this.events = new Events(); this.events = new Events();
this.logger = new Logger({logLevel: 'debug', events: this.events, context: this.context}); this.logger = new Logger({logLevel: 'debug', events: this.events, context: this.context});
this.config = new Config({env: env, logger: this.logger, events: this.events, context: this.context, version: this.version}); this.config = new Config({
env: env,
logger: this.logger,
events: this.events,
context: this.context,
version: this.version,
package: pkg
});
this.config.loadConfigFiles(options); this.config.loadConfigFiles(options);
this.plugins = this.config.plugins; this.plugins = this.config.plugins;
} }

View File

@ -1,116 +0,0 @@
import {normalizeInput} from 'embark-utils';
function dirname() {
const path = require('path');
return path.dirname.apply(path.dirname, arguments);
}
function filesMatchingPattern(files) {
const globule = require('globule');
return globule.find(files, {nonull: true});
}
function fileMatchesPattern(patterns, intendedPath) {
const globule = require('globule');
return globule.isMatch(patterns, intendedPath);
}
function cd(folder) {
const shelljs = require('shelljs');
shelljs.cd(folder);
}
function sed(file, pattern, replace) {
const shelljs = require('shelljs');
shelljs.sed('-i', pattern, replace, file);
}
function extractTar(filename, packageDirectory, cb) {
const o_fs = require('fs-extra');
const tar = require('tar');
o_fs.createReadStream(filename).pipe(
tar.x({
strip: 1,
C: packageDirectory
}).on('end', function () {
cb();
})
);
}
function extractZip(filename, packageDirectory, opts, cb) {
const decompress = require('decompress');
decompress(filename, packageDirectory, opts).then((_files) => {
cb();
});
}
function isValidDomain(v) {
// from: https://github.com/miguelmota/is-valid-domain
if (typeof v !== 'string') return false;
var parts = v.split('.');
if (parts.length <= 1) return false;
var tld = parts.pop();
var tldRegex = /^(?:xn--)?[a-zA-Z0-9]+$/gi;
if (!tldRegex.test(tld)) return false;
var isValid = parts.every(function(host) {
var hostRegex = /^(?!:\/\/)([a-zA-Z0-9]+|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])$/gi;
return hostRegex.test(host);
});
return isValid;
}
function interceptLogs(consoleContext, logger) {
let context = {};
context.console = consoleContext;
context.console.log = function () {
logger.info(normalizeInput(arguments));
};
context.console.warn = function () {
logger.warn(normalizeInput(arguments));
};
context.console.info = function () {
logger.info(normalizeInput(arguments));
};
context.console.debug = function () {
// TODO: ue JSON.stringify
logger.debug(normalizeInput(arguments));
};
context.console.trace = function () {
logger.trace(normalizeInput(arguments));
};
context.console.dir = function () {
logger.dir(normalizeInput(arguments));
};
}
function getWindowSize() {
const windowSize = require('window-size');
if (windowSize) {
return windowSize.get();
}
return {width: 240, height: 75};
}
module.exports = {
dirname,
filesMatchingPattern,
fileMatchesPattern,
isValidDomain,
cd,
sed,
extractTar,
extractZip,
normalizeInput,
interceptLogs,
getWindowSize
};

View File

@ -1,10 +1,19 @@
/*global __dirname, describe, it, before, after, require*/ /*global __dirname, describe, it, before, after, require*/
import { TestLogger } from 'embark-core';
import * as i18n from 'embark-i18n'; import * as i18n from 'embark-i18n';
const assert = require('assert'); const assert = require('assert');
const sinon = require('sinon'); const sinon = require('sinon');
let TestLogger = require('../lib/utils/test_logger');
const Web3 = require('web3'); const Web3 = require('web3');
import { dappPath, getWeiBalanceFromString, getHexBalanceFromString, AccountParser } from 'embark-utils'; import {
dappPath,
getWeiBalanceFromString,
getHexBalanceFromString,
AccountParser,
joinPath,
setUpEnv
} from 'embark-utils';
/* setUpEnv(joinPath(__dirname, '../../')); */
i18n.setOrDetectLocale('en'); i18n.setOrDetectLocale('en');
describe('embark.AccountParser', function () { describe('embark.AccountParser', function () {

View File

@ -1,10 +1,7 @@
/*global describe, it*/ /*global describe, it*/
import { Config, Events, Plugins, TestLogger } from 'embark-core';
const { dappPath } = require('embark-utils'); const { dappPath } = require('embark-utils');
const Config = require('../lib/core/config.js');
const Plugins = require('../lib/core/plugins.js');
const assert = require('assert'); const assert = require('assert');
const TestLogger = require('../lib/utils/test_logger');
const Events = require('../lib/core/events');
describe('embark.Config', function () { describe('embark.Config', function () {
let config = new Config({ let config = new Config({

View File

@ -3,15 +3,10 @@ import { File, Types } from "embark-utils";
let ContractsManager = require('embark-contracts-manager'); let ContractsManager = require('embark-contracts-manager');
let Compiler = require('embark-compiler'); let Compiler = require('embark-compiler');
let Logger = require('embark-logger'); import { Logger } from 'embark-logger';
import { IPC } from 'embark-core'; import { Events, fs, IPC, TestLogger, Plugins } from 'embark-core';
let TestLogger = require('../lib/utils/test_logger');
let Events = require('../lib/core/events');
const fs = require('../lib/core/fs');
let assert = require('assert'); let assert = require('assert');
let Plugins = require('../lib/core/plugins.js');
let readFile = function(file) { let readFile = function(file) {
return new File({filename: file, type: Types.dappFile, path: file}); return new File({filename: file, type: Types.dappFile, path: file});
}; };

View File

@ -1,9 +1,8 @@
/*globals describe, it, before, beforeEach*/ /*globals describe, it, before, beforeEach*/
import { Events, fs } from 'embark-core';
import { File, Types } from 'embark-utils'; import { File, Types } from 'embark-utils';
const Assert = require("assert"); const Assert = require("assert");
const {expect} = require("chai"); const {expect} = require("chai");
const fs = require("../lib/core/fs");
const Events = require("../lib/core/events");
let events; let events;
const testEventName = "testevent"; const testEventName = "testevent";

View File

@ -1,12 +1,10 @@
/*global describe, it, require*/ /*global describe, it, require*/
import { Events, Plugins, TestLogger } from 'embark-core';
import { File, Types } from "embark-utils"; import { File, Types } from "embark-utils";
const assert = require('assert'); const assert = require('assert');
const Compiler = require('embark-compiler'); const Compiler = require('embark-compiler');
const Plugins = require('../../../lib/core/plugins.js');
const TestLogger = require('../../../lib/utils/test_logger');
const Events = require('../../../lib/core/events');
const readFile = function(file) { const readFile = function(file) {
return new File({filename: file, type: Types.dappFile, path: file}); return new File({filename: file, type: Types.dappFile, path: file});

View File

@ -1,12 +1,10 @@
/*globals describe, it, beforeEach*/ /*globals describe, it, beforeEach*/
const {expect} = require('chai'); const {expect} = require('chai');
const sinon = require('sinon'); const sinon = require('sinon');
const fs = require('../../lib/core/fs'); import { Logger } from 'embark-logger';
const Events = require('../../lib/core/events');
const Logger = require('embark-logger');
import { getAddressToContract } from 'embark-utils'; import { getAddressToContract } from 'embark-utils';
const ConsoleListener = require('embark-console-listener'); const ConsoleListener = require('embark-console-listener');
import { IPC } from 'embark-core'; import { Events, fs, IPC } from 'embark-core';
require('colors'); require('colors');
let events, let events,

View File

@ -2,7 +2,6 @@
const { dappPath, File, Types, prepareForCompilation } = require('embark-utils'); const { dappPath, File, Types, prepareForCompilation } = require('embark-utils');
const path = require("path"); const path = require("path");
const {expect} = require("chai"); const {expect} = require("chai");
const fs = require("../../../lib/core/fs");
const fsNode = require("fs"); const fsNode = require("fs");
let file, content; let file, content;

View File

@ -1,9 +1,7 @@
/*global describe, it, require*/ /*global describe, it, require*/
const fs = require('../../../lib/core/fs'); import { fs, IPC, TestLogger } from 'embark-core';
import { IPC } from 'embark-core';
import { File, Types } from 'embark-utils'; import { File, Types } from 'embark-utils';
let SolidityCompiler = require('embark-solidity'); let SolidityCompiler = require('embark-solidity');
let TestLogger = require('../../../lib/utils/test_logger');
let readFile = function(file) { let readFile = function(file) {
return new File({filename: file, type: Types.dappFile, path: file}); return new File({filename: file, type: Types.dappFile, path: file});

View File

@ -1,9 +1,8 @@
/*global describe, it, before, beforeEach*/ /*global describe, it, before, beforeEach*/
const assert = require('assert'); const assert = require('assert');
const sinon = require('sinon'); const sinon = require('sinon');
const TestLogger = require('../lib/utils/test_logger');
const path = require('path'); const path = require('path');
import { ProcessLauncher } from 'embark-core'; import { ProcessLauncher, TestLogger } from 'embark-core';
let logger = new TestLogger({}); let logger = new TestLogger({});

View File

@ -1,6 +1,6 @@
/*globals describe, it, before*/ /*globals describe, it, before*/
const assert = require('assert'); const assert = require('assert');
const TemplateGenerator = require('../lib/utils/template_generator'); import { TemplateGenerator } from 'embark-core';
const semver = require('semver'); const semver = require('semver');
const sinon = require('sinon'); const sinon = require('sinon');
const request = require('request'); const request = require('request');

View File

@ -1,5 +1,4 @@
/*global describe, it*/ /*global describe, it*/
const Utils = require('../lib/utils/utils');
import { getExternalContractUrl } from 'embark-utils'; import { getExternalContractUrl } from 'embark-utils';
const assert = require('assert'); const assert = require('assert');
const constants = require('embark-core/constants'); const constants = require('embark-core/constants');

View File

@ -1,5 +1,5 @@
/*globals describe, it*/ /*globals describe, it*/
const TestLogger = require('../lib/utils/test_logger'); import { TestLogger } from 'embark-core';
import { VM } from 'embark-code-runner'; import { VM } from 'embark-code-runner';
const {expect} = require('chai'); const {expect} = require('chai');

View File

@ -51,6 +51,7 @@
"embark-core": "^5.0.0-alpha.1", "embark-core": "^5.0.0-alpha.1",
"embark-i18n": "^5.0.0-alpha.1", "embark-i18n": "^5.0.0-alpha.1",
"embark-utils": "^5.0.0-alpha.1", "embark-utils": "^5.0.0-alpha.1",
"embark-logger": "^5.0.0-alpha.1",
"web3": "1.2.1" "web3": "1.2.1"
}, },
"devDependencies": { "devDependencies": {

View File

@ -1,7 +1,8 @@
import async from "async"; import async from "async";
import { Embark, Events, Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark"; import { Embark, Events } /* supplied by @types/embark in packages/embark-typings */ from "embark";
import { __ } from "embark-i18n"; import { __ } from "embark-i18n";
import { AccountParser, dappPath } from "embark-utils"; import { AccountParser, dappPath } from "embark-utils";
import { Logger } from 'embark-logger';
import Web3 from "web3"; import Web3 from "web3";
const { blockchain: blockchainConstants } = require("embark-core/constants"); const { blockchain: blockchainConstants } = require("embark-core/constants");

View File

@ -1,5 +1,5 @@
import async from "async"; import async from 'async';
import { CmdLine } from "remix-debug-debugtest"; import { CmdLine } from 'remix-debug-debugtest';
export default class DebuggerManager { export default class DebuggerManager {
private nodeUrl: string; private nodeUrl: string;
@ -25,7 +25,7 @@ export default class DebuggerManager {
private debug(txHash: string, filename: string, cb: any) { private debug(txHash: string, filename: string, cb: any) {
const cmdLine = new CmdLine(); const cmdLine = new CmdLine();
cmdLine.connect("http", this.nodeUrl); cmdLine.connect('http', this.nodeUrl);
cmdLine.loadCompilationData(this.inputJson, this.outputJson); cmdLine.loadCompilationData(this.inputJson, this.outputJson);
cmdLine.initDebugger(() => { cmdLine.initDebugger(() => {
@ -48,7 +48,7 @@ export default class DebuggerManager {
async.waterfall([ async.waterfall([
function initDebugger(next: any) { function initDebugger(next: any) {
cmdLine = new CmdLine(); cmdLine = new CmdLine();
cmdLine.connect("http", self.nodeUrl); cmdLine.connect('http', self.nodeUrl);
cmdLine.loadCompilationData(self.inputJson, self.outputJson); cmdLine.loadCompilationData(self.inputJson, self.outputJson);
cmdLine.initDebugger(() => { cmdLine.initDebugger(() => {
// self.isDebugging = true // self.isDebugging = true
@ -57,19 +57,19 @@ export default class DebuggerManager {
}, },
function startDebug(next: any) { function startDebug(next: any) {
const debuggerData: any = {}; const debuggerData: any = {};
cmdLine.events.on("locals", (data: any) => { cmdLine.events.on('locals', (data: any) => {
debuggerData.locals = self.simplifyDebuggerVars(data); debuggerData.locals = self.simplifyDebuggerVars(data);
}); });
cmdLine.events.on("globals", (data: any) => { cmdLine.events.on('globals', (data: any) => {
debuggerData.contract = self.simplifyDebuggerVars(data); debuggerData.contract = self.simplifyDebuggerVars(data);
}); });
cmdLine.startDebug(txHash, filename, () => { cmdLine.startDebug(txHash, filename, () => {
cmdLine.events.on("source", () => { cmdLine.events.on('source', () => {
const lines: string[] = cmdLine.getSource(); const lines: string[] = cmdLine.getSource();
// TODO: this is a bit of a hack // TODO: this is a bit of a hack
const line: string = lines.filter((x) => x.indexOf("=>") === 0)[0]; const line: string = lines.filter((x) => x.indexOf('=>') === 0)[0];
outputCb(lines, line, debuggerData); outputCb(lines, line, debuggerData);
}); });

View File

@ -1,8 +1,8 @@
import "colors"; import 'colors';
import { __ } from "embark-i18n"; import { __ } from 'embark-i18n';
import DebuggerManager from "./debugger_manager"; import DebuggerManager from './debugger_manager';
const NO_DEBUG_SESSION = __("No debug session active. Activate one with `debug`"); const NO_DEBUG_SESSION = __('No debug session active. Activate one with `debug`');
interface Events { interface Events {
on: any; on: any;
@ -31,28 +31,28 @@ class TransactionDebugger {
constructor(embark: EmbarkApi, options?: any) { constructor(embark: EmbarkApi, options?: any) {
this.embark = embark; this.embark = embark;
this.debuggerManager = new DebuggerManager("http://localhost:8545"); this.debuggerManager = new DebuggerManager('http://localhost:8545');
embark.events.on("contracts:compile:solc", this.debuggerManager.setInputJson.bind(this.debuggerManager)); embark.events.on('contracts:compile:solc', this.debuggerManager.setInputJson.bind(this.debuggerManager));
embark.events.on("contracts:compiled:solc", this.debuggerManager.setOutputJson.bind(this.debuggerManager)); embark.events.on('contracts:compiled:solc', this.debuggerManager.setOutputJson.bind(this.debuggerManager));
this.txTracker = {}; this.txTracker = {};
this.lastTx = ""; this.lastTx = '';
this.isDebugging = false; this.isDebugging = false;
this.currentCmdTxHash = ""; this.currentCmdTxHash = '';
this.listenToEvents(); this.listenToEvents();
this.listenToCommands(); this.listenToCommands();
this.listentoAPI(); this.listentoAPI();
} }
private listenToEvents() { private listenToEvents() {
this.embark.events.on("blockchain:tx", (tx: any) => { this.embark.events.on('blockchain:tx', (tx: any) => {
this.embark.events.request("contracts:contract", tx.name, (contract: any) => { this.embark.events.request('contracts:contract', tx.name, (contract: any) => {
this.txTracker[tx.transactionHash] = {tx, contract}; this.txTracker[tx.transactionHash] = {tx, contract};
this.lastTx = tx.transactionHash; this.lastTx = tx.transactionHash;
if (tx.status !== "0x0") { return; } if (tx.status !== '0x0') { return; }
this.embark.logger.info("Transaction failed"); this.embark.logger.info('Transaction failed');
this.debuggerManager.getLastLine(tx.transactionHash, contract.filename, (lines: string[], line: string, knownVars: any) => { this.debuggerManager.getLastLine(tx.transactionHash, contract.filename, (lines: string[], line: string, knownVars: any) => {
lines.forEach((errorLine: string) => { lines.forEach((errorLine: string) => {
@ -60,7 +60,7 @@ class TransactionDebugger {
}); });
this.findVarsInLine(tx.transactionHash, line, knownVars, (foundVars: any) => { this.findVarsInLine(tx.transactionHash, line, knownVars, (foundVars: any) => {
if (!foundVars) { return; } if (!foundVars) { return; }
this.embark.logger.info("vars:"); this.embark.logger.info('vars:');
foundVars.forEach((variable: any) => { foundVars.forEach((variable: any) => {
this.embark.logger.info(`${variable.name}: ${variable.value}`); this.embark.logger.info(`${variable.name}: ${variable.value}`);
}); });
@ -84,7 +84,7 @@ class TransactionDebugger {
for (const variable of Object.keys(knownVars.locals || {})) { for (const variable of Object.keys(knownVars.locals || {})) {
const value: any = knownVars.locals[variable]; const value: any = knownVars.locals[variable];
const variableName: string = variable.split(" ")[0]; const variableName: string = variable.split(' ')[0];
if (line && line.indexOf(variableName) >= 0) { if (line && line.indexOf(variableName) >= 0) {
foundVars.push({name: variable, value}); foundVars.push({name: variable, value});
} }
@ -92,7 +92,7 @@ class TransactionDebugger {
for (const variable of Object.keys(knownVars.contract || {})) { for (const variable of Object.keys(knownVars.contract || {})) {
const value: any = knownVars.contract[variable]; const value: any = knownVars.contract[variable];
const variableName: string = variable.split(" ")[0]; const variableName: string = variable.split(' ')[0];
if (line && line.indexOf(variableName) >= 0) { if (line && line.indexOf(variableName) >= 0) {
foundVars.push({name: variable, value}); foundVars.push({name: variable, value});
} }
@ -106,10 +106,10 @@ class TransactionDebugger {
this.debuggerData = {}; this.debuggerData = {};
this.apiDebugger = false; this.apiDebugger = false;
this.embark.registerAPICall("post", "/embark-api/debugger/start", (req: any, res: any) => { this.embark.registerAPICall('post', '/embark-api/debugger/start', (req: any, res: any) => {
const txHash: string = req.body.params.txHash; const txHash: string = req.body.params.txHash;
this.embark.events.request("contracts:contract:byTxHash", txHash, (err: any, contract: any) => { this.embark.events.request('contracts:contract:byTxHash', txHash, (err: any, contract: any) => {
if (err) { if (err) {
this.embark.logger.error(err); this.embark.logger.error(err);
return res.send({error: err}); return res.send({error: err});
@ -136,55 +136,55 @@ class TransactionDebugger {
}); });
}); });
this.embark.registerAPICall("post", "/embark-api/debugger/stop", (req: any, res: any) => { this.embark.registerAPICall('post', '/embark-api/debugger/stop', (req: any, res: any) => {
this.apiDebugger.unload(); this.apiDebugger.unload();
this.apiDebugger.events.emit("stop"); this.apiDebugger.events.emit('stop');
this.apiDebugger = false; this.apiDebugger = false;
res.send({ok: true}); res.send({ok: true});
}); });
this.embark.registerAPICall("post", "/embark-api/debugger/JumpBack", (req: any, res: any) => { this.embark.registerAPICall('post', '/embark-api/debugger/JumpBack', (req: any, res: any) => {
this.apiDebugger.stepJumpNextBreakpoint(); this.apiDebugger.stepJumpNextBreakpoint();
res.send({ok: true}); res.send({ok: true});
}); });
this.embark.registerAPICall("post", "/embark-api/debugger/JumpForward", (req: any, res: any) => { this.embark.registerAPICall('post', '/embark-api/debugger/JumpForward', (req: any, res: any) => {
this.apiDebugger.stepJumpPreviousBreakpoint(); this.apiDebugger.stepJumpPreviousBreakpoint();
res.send({ok: true}); res.send({ok: true});
}); });
this.embark.registerAPICall("post", "/embark-api/debugger/StepOverForward", (req: any, res: any) => { this.embark.registerAPICall('post', '/embark-api/debugger/StepOverForward', (req: any, res: any) => {
if (this.apiDebugger.canGoNext()) { if (this.apiDebugger.canGoNext()) {
this.apiDebugger.stepOverForward(true); this.apiDebugger.stepOverForward(true);
} }
res.send({ok: true}); res.send({ok: true});
}); });
this.embark.registerAPICall("post", "/embark-api/debugger/StepOverBackward", (req: any, res: any) => { this.embark.registerAPICall('post', '/embark-api/debugger/StepOverBackward', (req: any, res: any) => {
if (this.apiDebugger.canGoPrevious()) { if (this.apiDebugger.canGoPrevious()) {
this.apiDebugger.stepOverBack(true); this.apiDebugger.stepOverBack(true);
} }
res.send({ok: true}); res.send({ok: true});
}); });
this.embark.registerAPICall("post", "/embark-api/debugger/StepIntoForward", (req: any, res: any) => { this.embark.registerAPICall('post', '/embark-api/debugger/StepIntoForward', (req: any, res: any) => {
if (this.apiDebugger.canGoNext()) { if (this.apiDebugger.canGoNext()) {
this.apiDebugger.stepIntoForward(true); this.apiDebugger.stepIntoForward(true);
} }
res.send({ok: true}); res.send({ok: true});
}); });
this.embark.registerAPICall("post", "/embark-api/debugger/StepIntoBackward", (req: any, res: any) => { this.embark.registerAPICall('post', '/embark-api/debugger/StepIntoBackward', (req: any, res: any) => {
if (this.apiDebugger.canGoPrevious()) { if (this.apiDebugger.canGoPrevious()) {
this.apiDebugger.stepIntoBack(true); this.apiDebugger.stepIntoBack(true);
} }
res.send({ok: true}); res.send({ok: true});
}); });
this.embark.registerAPICall("post", "/embark-api/debugger/breakpoint", (req: any, res: any) => { this.embark.registerAPICall('post', '/embark-api/debugger/breakpoint', (req: any, res: any) => {
res.send({ok: true}); res.send({ok: true});
}); });
this.embark.registerAPICall("ws", "/embark-api/debugger", (ws: any, req: any) => { this.embark.registerAPICall('ws', '/embark-api/debugger', (ws: any, req: any) => {
if (!this.apiDebugger) { return; } if (!this.apiDebugger) { return; }
this.apiDebugger.events.on("stop", () => { ws.close(1000); }); this.apiDebugger.events.on('stop', () => { ws.close(1000); });
this.apiDebugger.events.on("source", (lineColumnPos: any, rawLocation: any) => { this.apiDebugger.events.on('source', (lineColumnPos: any, rawLocation: any) => {
this.debuggerData.sources = {lineColumnPos, rawLocation}; this.debuggerData.sources = {lineColumnPos, rawLocation};
this.debuggerData.possibleSteps = { this.debuggerData.possibleSteps = {
canGoNext: this.apiDebugger.canGoNext(), canGoNext: this.apiDebugger.canGoNext(),
@ -193,7 +193,7 @@ class TransactionDebugger {
ws.send(JSON.stringify(this.debuggerData), () => {}); ws.send(JSON.stringify(this.debuggerData), () => {});
}); });
this.apiDebugger.events.on("locals", (data: any) => { this.apiDebugger.events.on('locals', (data: any) => {
this.debuggerData.locals = this.simplifyDebuggerVars(data); this.debuggerData.locals = this.simplifyDebuggerVars(data);
this.debuggerData.possibleSteps = { this.debuggerData.possibleSteps = {
canGoNext: this.apiDebugger.canGoNext(), canGoNext: this.apiDebugger.canGoNext(),
@ -202,7 +202,7 @@ class TransactionDebugger {
ws.send(JSON.stringify(this.debuggerData), () => {}); ws.send(JSON.stringify(this.debuggerData), () => {});
}); });
this.apiDebugger.events.on("globals", (data: any) => { this.apiDebugger.events.on('globals', (data: any) => {
this.debuggerData.contract = this.simplifyDebuggerVars(data); this.debuggerData.contract = this.simplifyDebuggerVars(data);
this.debuggerData.possibleSteps = { this.debuggerData.possibleSteps = {
canGoNext: this.apiDebugger.canGoNext(), canGoNext: this.apiDebugger.canGoNext(),
@ -227,27 +227,27 @@ class TransactionDebugger {
private listenToCommands() { private listenToCommands() {
this.cmdDebugger = false; this.cmdDebugger = false;
this.currentCmdTxHash = ""; this.currentCmdTxHash = '';
const self = this; const self = this;
function startDebug(txHash: string, filename: string, callback: (err?: string|object, output?: string) => void) { function startDebug(txHash: string, filename: string, callback: (err?: string|object, output?: string) => void) {
self.currentCmdTxHash = txHash; self.currentCmdTxHash = txHash;
self.embark.logger.info("debugging tx " + txHash); self.embark.logger.info('debugging tx ' + txHash);
self.cmdDebugger = self.debuggerManager.createDebuggerSession(txHash, filename, () => { self.cmdDebugger = self.debuggerManager.createDebuggerSession(txHash, filename, () => {
self.displayStepInfo(callback); self.displayStepInfo(callback);
}); });
} }
this.embark.registerConsoleCommand({ this.embark.registerConsoleCommand({
description: __("Start a debugging session using, the last transaction or the transaction specified by hash"), description: __('Start a debugging session using, the last transaction or the transaction specified by hash'),
matches: (cmd: string) => { matches: (cmd: string) => {
const [cmdName] = cmd.split(" "); const [cmdName] = cmd.split(' ');
return cmdName === "debug"; return cmdName === 'debug';
}, },
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => { process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
const [_cmdName, txHash] = cmd.split(" "); const [_cmdName, txHash] = cmd.split(' ');
if (txHash) { if (txHash) {
this.embark.events.request("contracts:contract:byTxHash", txHash, (err: any, contract: any) => { this.embark.events.request('contracts:contract:byTxHash', txHash, (err: any, contract: any) => {
if (err) { if (err) {
this.embark.logger.error(err); this.embark.logger.error(err);
return callback(); return callback();
@ -257,34 +257,34 @@ class TransactionDebugger {
}); });
return; return;
} }
if (this.lastTx === "") { if (this.lastTx === '') {
return callback(undefined, __("No transaction to debug")); return callback(undefined, __('No transaction to debug'));
} }
this.currentCmdTxHash = this.lastTx; this.currentCmdTxHash = this.lastTx;
const filename: string = this.txTracker[this.lastTx].contract.filename; const filename: string = this.txTracker[this.lastTx].contract.filename;
startDebug(this.lastTx, filename, callback); startDebug(this.lastTx, filename, callback);
}, },
usage: "debug [txHash]", usage: 'debug [txHash]',
}); });
this.embark.registerConsoleCommand({ this.embark.registerConsoleCommand({
description: __("Stops the active debugging session."), description: __('Stops the active debugging session.'),
matches: ["sd", "stop debugger"], matches: ['sd', 'stop debugger'],
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => { process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
if (!this.cmdDebugger) { if (!this.cmdDebugger) {
this.embark.logger.warn(NO_DEBUG_SESSION); this.embark.logger.warn(NO_DEBUG_SESSION);
return callback(); return callback();
} }
this.cmdDebugger = null; this.cmdDebugger = null;
this.embark.logger.info(__("The debug session has been stopped")); this.embark.logger.info(__('The debug session has been stopped'));
this.cmdDebugger.unload(); this.cmdDebugger.unload();
}, },
usage: " stop debugger/sd", usage: ' stop debugger/sd',
}); });
this.embark.registerConsoleCommand({ this.embark.registerConsoleCommand({
description: __("Step over forward on the current debugging session"), description: __('Step over forward on the current debugging session'),
matches: ["next", "n"], matches: ['next', 'n'],
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => { process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
if (!this.cmdDebugger) { if (!this.cmdDebugger) {
this.embark.logger.warn(NO_DEBUG_SESSION); this.embark.logger.warn(NO_DEBUG_SESSION);
@ -294,19 +294,19 @@ class TransactionDebugger {
return callback(); return callback();
} }
if (!this.cmdDebugger.currentStep()) { if (!this.cmdDebugger.currentStep()) {
this.embark.logger.info("end of execution reached"); this.embark.logger.info('end of execution reached');
this.cmdDebugger.unload(); this.cmdDebugger.unload();
return callback(); return callback();
} }
this.cmdDebugger.stepOverForward(true); this.cmdDebugger.stepOverForward(true);
this.displayStepInfo(callback); this.displayStepInfo(callback);
}, },
usage: " next/n", usage: ' next/n',
}); });
this.embark.registerConsoleCommand({ this.embark.registerConsoleCommand({
description: __("Step over back on the current debugging session"), description: __('Step over back on the current debugging session'),
matches: ["previous", "p"], matches: ['previous', 'p'],
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => { process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
if (!this.cmdDebugger) { if (!this.cmdDebugger) {
this.embark.logger.warn(NO_DEBUG_SESSION); this.embark.logger.warn(NO_DEBUG_SESSION);
@ -316,54 +316,54 @@ class TransactionDebugger {
return callback(); return callback();
} }
if (!this.cmdDebugger.currentStep()) { if (!this.cmdDebugger.currentStep()) {
this.embark.logger.info("end of execution reached"); this.embark.logger.info('end of execution reached');
return this.cmdDebugger.unload(); return this.cmdDebugger.unload();
} }
this.cmdDebugger.stepOverBack(true); this.cmdDebugger.stepOverBack(true);
this.displayStepInfo(callback); this.displayStepInfo(callback);
}, },
usage: " previous/p", usage: ' previous/p',
}); });
this.embark.registerConsoleCommand({ this.embark.registerConsoleCommand({
description: __("Display local variables of the current debugging session"), description: __('Display local variables of the current debugging session'),
matches: ["var local", "v l", "vl"], matches: ['var local', 'v l', 'vl'],
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => { process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
if (!this.cmdDebugger) { if (!this.cmdDebugger) {
this.embark.logger.warn(NO_DEBUG_SESSION); this.embark.logger.warn(NO_DEBUG_SESSION);
return callback(); return callback();
} }
this.embark.logger.info("Locals:"); this.embark.logger.info('Locals:');
const debugVars = this.simplifyDebuggerVars(this.cmdDebugger.solidityLocals); const debugVars = this.simplifyDebuggerVars(this.cmdDebugger.solidityLocals);
for (const debugVar of Object.keys(debugVars)) { for (const debugVar of Object.keys(debugVars)) {
this.embark.logger.info(`${debugVar}: ` + `${debugVars[debugVar]}`.white); this.embark.logger.info(`${debugVar}: ` + `${debugVars[debugVar]}`.white);
} }
callback(); callback();
}, },
usage: " var local/v l/vl", usage: ' var local/v l/vl',
}); });
this.embark.registerConsoleCommand({ this.embark.registerConsoleCommand({
description: __("Display global variables of the current debugging session"), description: __('Display global variables of the current debugging session'),
matches: ["var global", "v g", "vg"], matches: ['var global', 'v g', 'vg'],
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => { process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
if (!this.cmdDebugger) { if (!this.cmdDebugger) {
this.embark.logger.warn(NO_DEBUG_SESSION); this.embark.logger.warn(NO_DEBUG_SESSION);
return callback(); return callback();
} }
this.embark.logger.info("Globals:"); this.embark.logger.info('Globals:');
const debugVars = this.simplifyDebuggerVars(this.cmdDebugger.solidityState); const debugVars = this.simplifyDebuggerVars(this.cmdDebugger.solidityState);
for (const debugVar of Object.keys(debugVars)) { for (const debugVar of Object.keys(debugVars)) {
this.embark.logger.info(`${debugVar}: ` + `${debugVars[debugVar]}`.white); this.embark.logger.info(`${debugVar}: ` + `${debugVars[debugVar]}`.white);
} }
callback(); callback();
}, },
usage: " var global/v g/vg", usage: ' var global/v g/vg',
}); });
this.embark.registerConsoleCommand({ this.embark.registerConsoleCommand({
description: __("Display solidity global variables of the current debugging session"), description: __('Display solidity global variables of the current debugging session'),
matches: ["var all", "v a", "va"], matches: ['var all', 'v a', 'va'],
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => { process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
if (!this.cmdDebugger) { if (!this.cmdDebugger) {
this.embark.logger.warn(NO_DEBUG_SESSION); this.embark.logger.warn(NO_DEBUG_SESSION);
@ -374,37 +374,37 @@ class TransactionDebugger {
this.embark.logger.error(err); this.embark.logger.error(err);
return callback(); return callback();
} }
this.embark.logger.info("Solidity Global Variables:"); this.embark.logger.info('Solidity Global Variables:');
for (const debugVar of Object.keys(globals)) { for (const debugVar of Object.keys(globals)) {
this.embark.logger.info(`${debugVar}: ` + `${globals[debugVar]}`.white); this.embark.logger.info(`${debugVar}: ` + `${globals[debugVar]}`.white);
} }
callback(); callback();
}); });
}, },
usage: " var all/v a/va", usage: ' var all/v a/va',
}); });
} }
private getGlobals(txHash: string, cb: any) { private getGlobals(txHash: string, cb: any) {
const globals: any = {}; const globals: any = {};
this.embark.events.request("blockchain:getTransaction", txHash, (err: any, tx: any) => { this.embark.events.request('blockchain:getTransaction', txHash, (err: any, tx: any) => {
if (err) { return cb(err); } if (err) { return cb(err); }
this.embark.events.request("blockchain:block:byHash", tx.blockHash, (errHash: any, block: any) => { this.embark.events.request('blockchain:block:byHash', tx.blockHash, (errHash: any, block: any) => {
if (errHash) { return cb(errHash); } if (errHash) { return cb(errHash); }
/* tslint:disable:no-string-literal */ /* tslint:disable:no-string-literal */
globals["block.blockHash"] = tx.blockHash; globals['block.blockHash'] = tx.blockHash;
globals["block.number"] = tx.blockNumber; globals['block.number'] = tx.blockNumber;
globals["block.coinbase"] = block.miner; globals['block.coinbase'] = block.miner;
globals["block.difficulty"] = block.difficulty; globals['block.difficulty'] = block.difficulty;
globals["block.gaslimit"] = block.gasLimit; globals['block.gaslimit'] = block.gasLimit;
globals["block.timestamp"] = block.timestamp; globals['block.timestamp'] = block.timestamp;
globals["msg.sender"] = tx.from; globals['msg.sender'] = tx.from;
globals["msg.gas"] = tx.gas; globals['msg.gas'] = tx.gas;
globals["msg.gasPrice"] = tx.gasPrice; globals['msg.gasPrice'] = tx.gasPrice;
globals["msg.value"] = tx.value; globals['msg.value'] = tx.value;
globals["now"] = block.timestamp; globals['now'] = block.timestamp;
/* tslint:enable:no-string-literal */ /* tslint:enable:no-string-literal */
cb(null, globals); cb(null, globals);
@ -414,24 +414,24 @@ class TransactionDebugger {
private displayPossibleActions() { private displayPossibleActions() {
const actions: string[] = []; const actions: string[] = [];
actions.push("actions: "); actions.push('actions: ');
if (this.cmdDebugger.canGoPrevious()) { if (this.cmdDebugger.canGoPrevious()) {
actions.push("(p)revious"); actions.push('(p)revious');
} }
if (this.cmdDebugger.canGoNext()) { if (this.cmdDebugger.canGoNext()) {
actions.push("(n)ext"); actions.push('(n)ext');
} }
actions.push("(vl) var local"); actions.push('(vl) var local');
actions.push("(vg) var global"); actions.push('(vg) var global');
actions.push("(va) var all"); actions.push('(va) var all');
actions.push("(sd) stop debugger"); actions.push('(sd) stop debugger');
if (actions.length === 1) { return; } if (actions.length === 1) { return; }
this.embark.logger.info(""); this.embark.logger.info('');
this.embark.logger.info(actions.join(" | ")); this.embark.logger.info(actions.join(' | '));
} }
private displayVarsInLine(cb?: any) { private displayVarsInLine(cb?: any) {
@ -450,7 +450,7 @@ class TransactionDebugger {
if (!foundVars) { if (!foundVars) {
return cb ? cb() : null; return cb ? cb() : null;
} }
this.embark.logger.info("vars:"); this.embark.logger.info('vars:');
foundVars.forEach((variable: any) => { foundVars.forEach((variable: any) => {
this.embark.logger.info(`${variable.name}: ` + `${variable.value}`.white); this.embark.logger.info(`${variable.name}: ` + `${variable.value}`.white);
}); });

View File

@ -44,6 +44,7 @@
"dependencies": { "dependencies": {
"colors": "1.3.2", "colors": "1.3.2",
"embark-utils": "^5.0.0-alpha.1", "embark-utils": "^5.0.0-alpha.1",
"embark-logger": "^5.0.0-alpha.1",
"fs-extra": "8.1.0", "fs-extra": "8.1.0",
"web3": "1.2.1" "web3": "1.2.1"
}, },

View File

@ -5,7 +5,7 @@ const fs = require('fs-extra');
const sinon = require('sinon'); const sinon = require('sinon');
const expect = require('expect.js'); const expect = require('expect.js');
import {beforeEach, afterEach} from "mocha"; import {beforeEach, afterEach} from "mocha";
import Logger from "embark-logger"; import { Logger } from "embark-logger";
require("colors"); require("colors");
describe('embark.deploymentChecks', function () { describe('embark.deploymentChecks', function () {

View File

@ -4,7 +4,7 @@ const fs = require('fs-extra');
const sinon = require('sinon'); const sinon = require('sinon');
const expect = require('expect.js'); const expect = require('expect.js');
import {beforeEach, afterEach} from "mocha"; import {beforeEach, afterEach} from "mocha";
import Logger from "embark-logger"; import { Logger } from "embark-logger";
import {dappPath} from 'embark-utils'; import {dappPath} from 'embark-utils';
require("colors"); require("colors");

View File

@ -10,7 +10,7 @@ const WhisperGethClient = require('./whisperClient.js');
import { IPC } from 'embark-core'; import { IPC } from 'embark-core';
import { compact, dappPath, defaultHost, dockerHostSwap, embarkPath} from 'embark-utils'; import { compact, dappPath, defaultHost, dockerHostSwap, embarkPath} from 'embark-utils';
const Logger = require('embark-logger'); import { Logger } from 'embark-logger';
// time between IPC connection attempts (in ms) // time between IPC connection attempts (in ms)
const IPC_CONNECT_INTERVAL = 2000; const IPC_CONNECT_INTERVAL = 2000;

View File

@ -10,7 +10,7 @@ const ParityClient = require('./parityClient.js');
import {IPC} from 'embark-core'; import {IPC} from 'embark-core';
import {compact, dappPath, defaultHost, dockerHostSwap, embarkPath/*, AccountParser*/} from 'embark-utils'; import {compact, dappPath, defaultHost, dockerHostSwap, embarkPath/*, AccountParser*/} from 'embark-utils';
const Logger = require('embark-logger'); import { Logger } from 'embark-logger';
// time between IPC connection attempts (in ms) // time between IPC connection attempts (in ms)
const IPC_CONNECT_INTERVAL = 2000; const IPC_CONNECT_INTERVAL = 2000;

View File

@ -47,6 +47,7 @@
"core-js": "3.3.5", "core-js": "3.3.5",
"embark-i18n": "^5.0.0-alpha.1", "embark-i18n": "^5.0.0-alpha.1",
"embark-utils": "^5.0.0-alpha.1", "embark-utils": "^5.0.0-alpha.1",
"embark-logger": "^5.0.0-alpha.1",
"handlebars": "4.2.0" "handlebars": "4.2.0"
}, },
"devDependencies": { "devDependencies": {

View File

@ -1,6 +1,6 @@
import Ajv from "ajv"; import Ajv from "ajv";
import { Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark";
import { __ } from "embark-i18n"; import { __ } from "embark-i18n";
import { Logger } from 'embark-logger';
export enum Framework { export enum Framework {
React = "react", React = "react",

View File

@ -1,5 +1,5 @@
import Ajv from "ajv"; import Ajv from "ajv";
import { Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark"; import { Logger } from 'embark-logger';
import { __ } from "embark-i18n"; import { __ } from "embark-i18n";
import { schema } from "./schema"; import { schema } from "./schema";
const fs = require("fs"); const fs = require("fs");

View File

@ -48,7 +48,8 @@
"core-js": "3.3.5", "core-js": "3.3.5",
"embark-core": "^5.0.0-alpha.1", "embark-core": "^5.0.0-alpha.1",
"embark-i18n": "^5.0.0-alpha.1", "embark-i18n": "^5.0.0-alpha.1",
"embark-utils": "^5.0.0-alpha.1" "embark-utils": "^5.0.0-alpha.1",
"embark-logger": "^5.0.0-alpha.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.6.4", "@babel/core": "7.6.4",

View File

@ -1,4 +1,5 @@
import { Embark, Events, Logger } from "embark"; import { Embark, Events } from "embark";
import { Logger } from 'embark-logger';
export default class BlockchainAPI { export default class BlockchainAPI {
private embark: Embark; private embark: Embark;
private logger: Logger; private logger: Logger;

View File

@ -53,6 +53,7 @@
"embark-core": "^5.0.0-alpha.1", "embark-core": "^5.0.0-alpha.1",
"embark-i18n": "^5.0.0-alpha.1", "embark-i18n": "^5.0.0-alpha.1",
"embark-utils": "^5.0.0-alpha.1", "embark-utils": "^5.0.0-alpha.1",
"embark-logger": "^5.0.0-alpha.1",
"web3": "1.2.1" "web3": "1.2.1"
}, },
"devDependencies": { "devDependencies": {

View File

@ -1,4 +1,5 @@
import { ContractConfig, Logger } from "embark"; import { ContractConfig } from "embark";
import { Logger } from 'embark-logger';
const { sha3 } = require("embark-utils"); const { sha3 } = require("embark-utils");
import { ABIDefinition } from "web3/eth/abi"; import { ABIDefinition } from "web3/eth/abi";

View File

@ -51,6 +51,7 @@
"embark-core": "^5.0.0-alpha.1", "embark-core": "^5.0.0-alpha.1",
"embark-i18n": "^5.0.0-alpha.1", "embark-i18n": "^5.0.0-alpha.1",
"embark-utils": "^5.0.0-alpha.1", "embark-utils": "^5.0.0-alpha.1",
"embark-logger": "^5.0.0-alpha.1",
"express": "4.17.1", "express": "4.17.1",
"express-ws": "4.0.0", "express-ws": "4.0.0",
"web3-core-requestmanager": "1.2.1", "web3-core-requestmanager": "1.2.1",

View File

@ -1,6 +1,7 @@
import { Embark, Events, Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark"; import {Embark, Events } /* supplied by @types/embark in packages/embark-typings */ from "embark";
import { __ } from "embark-i18n"; import {__} from "embark-i18n";
import { buildUrl, findNextPort } from "embark-utils"; import { buildUrl, findNextPort } from "embark-utils";
import { Logger } from 'embark-logger';
import { Proxy } from "./proxy"; import { Proxy } from "./proxy";
const constants = require("embark-core/constants"); const constants = require("embark-core/constants");

View File

@ -44,6 +44,8 @@
"@babel/core": "7.6.4", "@babel/core": "7.6.4",
"@babel/plugin-proposal-class-properties": "7.5.5", "@babel/plugin-proposal-class-properties": "7.5.5",
"@babel/plugin-proposal-decorators": "7.6.0", "@babel/plugin-proposal-decorators": "7.6.0",
"@babel/plugin-proposal-export-namespace-from": "7.5.2",
"@babel/plugin-proposal-export-default-from": "7.5.2",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.4.4", "@babel/plugin-proposal-nullish-coalescing-operator": "7.4.4",
"@babel/plugin-proposal-optional-chaining": "7.6.0", "@babel/plugin-proposal-optional-chaining": "7.6.0",
"@babel/plugin-syntax-dynamic-import": "7.2.0", "@babel/plugin-syntax-dynamic-import": "7.2.0",

View File

@ -6,6 +6,7 @@
"module": "CommonJS", "module": "CommonJS",
"noEmit": true, "noEmit": true,
"noImplicitThis": false, "noImplicitThis": false,
"noImplicitAny": false,
"strict": true, "strict": true,
"target": "ES2017", "target": "ES2017",
"resolveJsonModule": true "resolveJsonModule": true

View File

@ -5,13 +5,20 @@
], ],
"jsRules": {}, "jsRules": {},
"rules": { "rules": {
"arrow-parens": false,
"interface-name": [true, "never-prefix"], "interface-name": [true, "never-prefix"],
"max-line-length": [true, 200], "max-line-length": [true, 200],
"member-ordering": [false], "member-ordering": [false],
"member-access": false,
"no-empty": false, "no-empty": false,
"no-console": false, "no-console": false,
"no-var-requires": false, "no-var-requires": false,
"variable-name": ["allow-leading-underscore"] "variable-name": ["allow-leading-underscore"],
"object-literal-sort-keys": false,
"ordered-imports": false,
"quotemark": [false, "single"],
"trailing-comma": false,
"no-irregular-whitespace": false
}, },
"rulesDirectory": [] "rulesDirectory": []
} }

2645
yarn.lock

File diff suppressed because it is too large Load Diff