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

This commit is contained in:
Pascal Precht 2019-11-11 14:41:40 +01:00 committed by Pascal Precht
parent 8733ca911c
commit d2556af8ba
87 changed files with 2249 additions and 2158 deletions

View File

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

View File

@ -52,6 +52,8 @@
"core-js": "3.3.5",
"embark-utils": "^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",
"parse-json": "4.0.0",
"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 { Logger } from 'embark-logger';
import * as fs from "./fs";
import VM from "./vm";
export { fs, VM };
import { Callback, Embark, Events, Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark";
class CodeRunner {
private logger: Logger;
private events: Events;

View File

@ -1,6 +1,7 @@
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 { Logger } from 'embark-logger';
import * as path from "path";
import { NodeVM, NodeVMOptions } from "vm2";

View File

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

View File

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

View File

@ -34,29 +34,44 @@
"_build": "npm run solo -- build",
"ci": "npm run qa",
"clean": "npm run reset",
"lint": "eslint process.js src/",
"qa": "npm-run-all lint _build",
"lint": "npm-run-all lint:*",
"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",
"solo": "embark-solo"
"solo": "embark-solo",
"typecheck": "tsc"
},
"eslintConfig": {
"extends": "../../../.eslintrc.json"
},
"dependencies": {
"@babel/runtime-corejs3": "7.6.3",
"colors": "1.3.2",
"core-js": "3.3.5",
"embark-i18n": "^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",
"fs-extra": "8.1.0",
"globule": "1.2.1",
"lodash.clonedeep": "4.5.0",
"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": {
"@babel/core": "7.6.4",
"babel-jest": "24.9.0",
"embark-solo": "^5.0.0-alpha.0",
"eslint": "5.7.0",
"npm-run-all": "4.1.5",
"rimraf": "3.0.0"
"rimraf": "3.0.0",
"tslint": "5.16.0",
"typescript": "3.6.3"
},
"engines": {
"node": ">=10.17.0 <12.0.0",

View File

@ -0,0 +1,758 @@
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 configObject = {
default: {
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,22 +39,22 @@ export function getBlockchainDefaults(env) {
export function getContractDefaults(embarkConfigVersions) {
const defaultVersions = {
"solc": "0.5.0"
solc: "0.5.0"
};
const versions = recursiveMerge(defaultVersions, embarkConfigVersions || {});
return {
"default": {
"versions": versions,
"dappConnection": [
default: {
versions: versions,
dappConnection: [
"$WEB3",
"ws://localhost:8546",
"localhost:8545"
],
"dappAutoEnable": true,
"strategy": constants.deploymentStrategy.implicit,
"gas": "auto",
"deploy": {
dappAutoEnable: true,
strategy: constants.deploymentStrategy.implicit,
gas: "auto",
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 utils = require('../utils/utils');
const Logger = require('embark-logger');
export class Engine {
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) {
this.env = options.env;
this.client = options.client;
@ -21,24 +73,23 @@ class Engine {
this.webServerConfig = options.webServerConfig;
this.webpackConfigName = options.webpackConfigName;
this.singleUseAuthToken = options.singleUseAuthToken;
this.package = options.package;
this.ipcRole = options.ipcRole || 'client';
}
init(_options, callback) {
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.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.plugins = this.config.plugins;
this.isDev = this.config && this.config.blockchainConfig && (this.config.blockchainConfig.isDev || this.config.blockchainConfig.default);
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});
@ -55,6 +106,7 @@ class Engine {
}
startEngine(cb) {
if (this.plugins) {
this.plugins.emitAndRunActionsForEvent("embark:engine:started", {}, (err) => {
if (err) {
console.error("error starting engine");
@ -63,20 +115,27 @@ class Engine {
}
cb();
});
} else {
cb();
}
}
registerModule(moduleName, options) {
if (this.plugins) {
this.plugins.loadInternalPlugin(moduleName, options || {});
}
}
registerModulePackage(moduleName, options) {
registerModulePackage(moduleName, options?: any) {
if (this.plugins) {
return this.plugins.loadInternalPlugin(moduleName, options || {}, true);
}
}
registerModuleGroup(groupName, _options) {
let options = _options || {};
const options = _options || {};
let groups = {
const groups = {
blockchain: this.blockchainComponents,
coreComponents: this.coreComponents,
stackComponents: this.stackComponents,
@ -94,7 +153,7 @@ class Engine {
cockpit: this.cockpitModules
};
let group = groups[groupName];
const group = groups[groupName];
if (!group) {
throw new Error("unknown service: " + groupName);
@ -122,6 +181,7 @@ class Engine {
}
coreComponents() {
// TODO: should be made into a component
this.processManager = new ProcessManager({
events: this.events,
@ -129,17 +189,22 @@ class Engine {
plugins: this.plugins
});
const ServicesMonitor = require('./services_monitor.js');
this.servicesMonitor = new ServicesMonitor({events: this.events, logger: this.logger, plugins: this.plugins});
if (this.servicesMonitor) {
this.servicesMonitor.addCheck('Embark', (cb) => {
return cb({name: 'Embark ' + this.version, status: 'on'});
}, 0);
let plugin = this.plugins.createPlugin('coreservicesplugin', {});
if (this.plugins) {
const plugin = this.plugins.createPlugin('coreservicesplugin', {});
plugin.registerActionForEvent("embark:engine:started", (_params, cb) => {
this.servicesMonitor.startMonitor();
this.servicesMonitor && this.servicesMonitor.startMonitor();
cb();
});
}
}
this.registerModulePackage('embark-code-runner', {ipc: this.ipc});
// TODO: we shouldn't need useDashboard
@ -236,14 +301,35 @@ class Engine {
this.registerModulePackage('embark-ens');
}
cockpitModules() {
this.registerModulePackage('embark-authenticator', {singleUseAuthToken: this.singleUseAuthToken});
this.registerModulePackage('embark-api', {plugins: this.plugins});
// Register logs for the cockpit console
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';
var EventEmitter = require('events');
const EventEmitter = require('events');
const cloneDeep = require('lodash.clonedeep');
const fs = require('fs-extra');
@ -8,22 +8,26 @@ function debugEventsEnabled() {
return process && process.env && process.env.DEBUGEVENTS;
}
function warnIfLegacy(eventName) {
const legacyEvents = [];
function warnIfLegacy(eventName: string) {
const legacyEvents: string[] = [];
if (legacyEvents.indexOf(eventName) >= 0) {
console.info(__("this event is deprecated and will be removed in future versions %s", eventName));
}
}
function getOrigin() {
if (!(debugEventsEnabled())) return "";
let origin = ((new Error().stack).split("at ")[3]).trim();
if (!(debugEventsEnabled())) { return ""; }
const stack = new Error().stack;
if (stack) {
let origin = stack.split("at ")[3].trim();
origin = origin.split("(")[0].trim();
return origin;
}
return '';
}
function log(eventType, eventName, origin) {
if (!(debugEventsEnabled())) return;
function log(eventType, eventName, origin?: string) {
if (!(debugEventsEnabled())) { return; }
if (['end', 'prefinish', 'error', 'new', 'demo', 'block', 'version'].indexOf(eventName) >= 0) {
return;
}
@ -32,8 +36,11 @@ function log(eventType, eventName, origin) {
}
// fs.appendFileSync(".embark/events.log", (new Error().stack) + "\n");
if (!origin && origin !== "") {
origin = ((new Error().stack).split("at ")[3]).trim();
const stack = new Error().stack;
if (stack) {
origin = stack.split("at ")[3].trim();
origin = origin.split("(")[0].trim();
}
// origin = getOrigin();
}
@ -50,7 +57,7 @@ function log(eventType, eventName, origin) {
// cmdNames[cmdName] = origin;
// }
class EmbarkEmitter extends EventEmitter {
export class EmbarkEmitter extends EventEmitter {
emit(requestName, ...args) {
warnIfLegacy(arguments[0]);
@ -59,7 +66,6 @@ class EmbarkEmitter extends EventEmitter {
}
}
// EmbarkEmitter.prototype.log = log;
EmbarkEmitter.prototype.log = log;
@ -98,8 +104,8 @@ EmbarkEmitter.prototype.setHandler = function(requestName, cb) {
};
EmbarkEmitter.prototype.request2 = function() {
let requestName = arguments[0];
let other_args = [].slice.call(arguments, 1);
const requestName = arguments[0];
const other_args: any[] = [].slice.call(arguments, 1);
log("\nREQUEST", 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(
(err, ...res) => {
if (err) return reject(err);
if (err) { return reject(err); }
if (res.length && res.length > 1) {
return resolve(res);
}
@ -126,7 +132,7 @@ EmbarkEmitter.prototype.request2 = function() {
this._emit('request:' + requestName, ...other_args);
});
let ogStack = (new Error().stack);
const ogStack = (new Error().stack);
promise.catch((e) => {
if (debugEventsEnabled()) {
@ -141,8 +147,8 @@ EmbarkEmitter.prototype.request2 = function() {
};
EmbarkEmitter.prototype.request = function() {
let requestName = arguments[0];
let other_args = [].slice.call(arguments, 1);
const requestName = arguments[0];
const other_args = [].slice.call(arguments, 1);
log("\nREQUEST(OLD)", requestName);
warnIfLegacy(requestName);
@ -177,9 +183,9 @@ EmbarkEmitter.prototype.setCommandHandler = function(requestName, cb) {
// let origin = ((new Error().stack).split("at ")[3]).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);
cb.call(this, ...arguments);
};
@ -232,5 +238,3 @@ EmbarkEmitter.prototype.setCommandHandlerOnce = function(requestName, cb) {
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) { return fs.statSync(args); }
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,370 @@
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');
// Default priority of actions with no specified priority. 1 => Highest
const DEFAULT_ACTION_PRIORITY = 50;
// 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, options?, cb?) {
if (typeof options === 'function') {
cb = options;
options = {};
}
if (!this.eventActions[eventName]) {
this.eventActions[eventName] = [];
}
this.eventActions[eventName].push({action: cb, options: Object.assign({priority: DEFAULT_ACTION_PRIORITY}, options)});
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,284 @@
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);
}
actionPlugins.sort((a, b) => {
const aPriority = a[0].options.priority;
const bPriority = b[0].options.priority;
if (aPriority < bPriority) {
return -1;
}
if (aPriority > bPriority) {
return 1;
}
return 0;
});
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.action.name, pluginName);
if (typeof (args) === 'function') {
plugin.action.call(plugin.action, (...params) => {
nextEach(...params || current_args);
});
} else {
plugin.action.call(plugin.action, 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';
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 utils = require('./utils.js');
import { filesMatchingPattern } from './utils';
import {
embarkPath,
downloadFile,
@ -27,7 +32,7 @@ const REPLACEMENTS = {
'gitlab.com/': 'gitlab:'
};
class TemplateGenerator {
export class TemplateGenerator {
constructor(templateName) {
this.isInsideMonorepo = isInsideMonorepoSync();
if (this.isInsideMonorepo) {
@ -46,7 +51,7 @@ class TemplateGenerator {
async download(url, tmpFilePath, browse) {
console.log(__('Installing template from ' + browse).green);
console.log(__('Downloading template...').green);
fs.mkdirpSync(utils.dirname(tmpFilePath));
fs.mkdirpSync(path.dirname(tmpFilePath));
try {
await promisify(downloadFile)(url, tmpFilePath);
} catch (e) {
@ -96,7 +101,7 @@ class TemplateGenerator {
}
extract(filePath, destinationFolder, cb = () => {}) {
utils.extractZip(
extractZip(
filePath,
destinationFolder,
{
@ -139,7 +144,7 @@ class TemplateGenerator {
);
execSync(`npm pack ${templateSpecifier}`, {cwd: tmpDir, stdio: 'ignore'});
const packed = utils.filesMatchingPattern(
const packed = filesMatchingPattern(
[joinPath(tmpDir, '*.tgz')]
)[0];
@ -162,7 +167,7 @@ class TemplateGenerator {
}
installTemplate(templatePath, name, installPackages, cb) {
utils.cd(templatePath);
shelljs.cd(templatePath);
const pkgJson = fs.readJSONSync('./package.json');
if (!(/demo/).test(name)) {
@ -260,7 +265,7 @@ class TemplateGenerator {
let templateAndBranch = uri.split('#');
if (templateAndBranch.length === 1) {
fallback = true;
embarkVersion = semver(require('../../../package.json').version);
embarkVersion = semver(require(embarkPath('package.json')).version);
templateAndBranch.push(`${embarkVersion.major}.${embarkVersion.minor}`);
}
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
// for this
class TestLogger {
export class TestLogger {
constructor(options) {
this.logLevels = ['error', 'warn', 'info', 'debug', 'trace'];
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 * as i18n from "i18n";
import { Maybe } from 'embark';
import * as i18n from 'i18n';
declare module "embark-i18n" {
declare module 'embark-i18n' {
function setOrDetectLocale(locale: Maybe<string>): void;
function __(
phraseOrOptions: string | i18n.TranslateOptions,

View File

@ -1,20 +1,20 @@
import colors from "colors/safe";
import * as i18n from "i18n";
import * as osLocale from "os-locale";
import * as path from "path";
import colors from 'colors/safe';
import * as i18n from 'i18n';
import * as osLocale from 'os-locale';
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 {
Specified = "specified",
Detected = "detected",
Specified = 'specified',
Detected = 'detected',
}
enum SupportedLanguage {
En = "en",
Pt = "pt",
Fr = "fr",
Es = "es",
En = 'en',
Pt = 'pt',
Fr = 'fr',
Es = 'es',
}
const DEFAULT_LANGUAGE = SupportedLanguage.En;
@ -22,7 +22,7 @@ const DEFAULT_LANGUAGE = SupportedLanguage.En;
const i18nEmbark = { __: null };
i18n.configure({
directory: path.join(__dirname, "../", "locales"),
directory: path.join(__dirname, '../', 'locales'),
locales: Object.values(SupportedLanguage),
register: i18nEmbark,
syncFiles: false,

View File

@ -7,7 +7,7 @@ const util = require('util');
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);
class Logger {
export class Logger {
constructor(options) {
this.events = options.events || {emit: function(){}};
this.logLevels = Object.keys(Logger.logLevels);
@ -167,5 +167,3 @@ Logger.prototype.dir = function (txt) {
Logger.prototype.shouldLog = function (level) {
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/remix-debug-debugtest";
import './src/prettier-plugin-solidity';
import './src/remix-debug-debugtest';
export * from "./src/callbacks";
export * from "./src/contract";
export * from "./src/embark";
export * from "./src/contractsConfig";
export * from "./src/embarkConfig";
export * from "./src/logger";
export * from "./src/maybe";
export * from "./src/plugins";
export * from './src/callbacks';
export * from './src/contract';
export * from './src/embark';
export * from './src/contractsConfig';
export * from './src/embarkConfig';
export * from './src/logger';
export * from './src/maybe';
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 {
abiDefinition: ABIDefinition[];

View File

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

View File

@ -1,4 +1,4 @@
import {Callback} from "./callbacks";
import {Callback} from './callbacks';
export interface Plugin {
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 dockerHostSwap(host: 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 diagramPath(...names: string[]): string;
function escapeHtml(message: any): string;

View File

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

View File

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

View File

@ -1,6 +1,6 @@
const ZERO_ADDRESS_SHORTHAND_REGEX = /^0x0$/;
const ZERO_ADDRESS_SHORTHAND_SEARCH_REGEX = /'0x0'/g;
export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
export function extendZeroAddressShorthand(value: string) {
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) {
return array[array.length - 1];

View File

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

View File

@ -1,17 +1,17 @@
const {execSync} = require("child_process");
const {hostname} = require("os");
const {execSync} = require('child_process');
const {hostname} = require('os');
const isDocker = (() => {
// assumption: an Embark container is always a Linux Docker container, though
// the Docker host may be Linux, macOS, or Windows
if (process.platform !== "linux") { return false; }
if (process.platform !== 'linux') { return false; }
try {
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(
execSync(
"cat /proc/self/cgroup",
{stdio: ["ignore", "pipe", "ignore"]},
'cat /proc/self/cgroup',
{stdio: ['ignore', 'pipe', 'ignore']},
).toString(),
);
} 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
// 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
// swap 0.0.0.0 for localhost in code/messages that pertain to client-side
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 {
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);

View File

@ -3,27 +3,36 @@ const https = require('follow-redirects').https;
const shelljs = require('shelljs');
const clipboardy = require('clipboardy');
const {canonicalHost, defaultCorsHost, defaultHost, dockerHostSwap, isDocker} = require('./host');
const {downloadFile, findNextPort, getJson, httpGet, httpsGet, httpGetJson, httpsGetJson, pingEndpoint} = require('./network');
import { canonicalHost } from './host';
export { canonicalHost, defaultCorsHost, defaultHost, dockerHostSwap, isDocker } from './host';
export { downloadFile, findNextPort, getJson, httpGet, httpsGet, httpGetJson, httpsGetJson, pingEndpoint } from './network';
const logUtils = require('./log-utils');
export const escapeHtml = logUtils.escapeHtml;
export const normalizeInput = logUtils.normalizeInput;
export { LogHandler } from './logHandler';
const toposortGraph = require('./toposort');
import { unitRegex } from './constants';
import * as AddressUtils from './addressUtils';
import {
getWeiBalanceFromString,
getHexBalanceFromString,
hexToNumber,
export { AddressUtils };
import { unitRegex } from './constants';
export { unitRegex } from './constants';
import { isHex, getWeiBalanceFromString } from './web3Utils';
export {
decodeParams,
isHex,
getHexBalanceFromString,
getWeiBalanceFromString,
hexToNumber,
sha3,
sha512,
isHex,
soliditySha3,
toChecksumAddress
} from './web3Utils';
import { getAddressToContract, getTransactionParams } from './transactionUtils';
export { getAddressToContract, getTransactionParams } from './transactionUtils';
import LongRunningProcessTimer from './longRunningProcessTimer';
export { LongRunningProcessTimer };
import AccountParser from './accountParser';
import {
export { AccountParser };
export {
anchoredValue,
dappPath,
diagramPath,
@ -42,15 +51,15 @@ import {
normalizePath,
toForwardSlashes
} from './pathUtils';
import { setUpEnv } from './env';
export { setUpEnv } from './env';
const { extendZeroAddressShorthand, replaceZeroAddressShorthand } = AddressUtils;
import { compact, last, recursiveMerge, groupBy } from './collections';
import { prepareForCompilation } from './solidity/remapImports';
import { File, getExternalContractUrl, Types } from './file';
export { compact, last, recursiveMerge, groupBy } from './collections';
export { prepareForCompilation } from './solidity/remapImports';
export { File, getExternalContractUrl, Types } from './file';
import {
export {
findMonorepoPackageFromRoot,
findMonorepoPackageFromRootSync,
isInsideMonorepo,
@ -59,25 +68,23 @@ import {
monorepoRootPathSync
} from './monorepo';
function timer(ms) {
export function timer(ms: number) {
const then = Date.now();
return new Promise(resolve => (
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 httpObj = (protocol === 'https') ? https : http;
httpObj.get(url, function (_res) {
callback(true);
}).on('error', function (_res) {
callback(false);
});
httpObj
.get(url, (_res: any) => callback(true))
.on('error', (_res: any) => callback(false));
}
function hashTo32ByteHexString(hash) {
export function hashTo32ByteHexString(hash: string) {
if (isHex(hash)) {
if (!hash.startsWith('0x')) {
hash = '0x' + hash;
@ -85,23 +92,23 @@ function hashTo32ByteHexString(hash) {
return hash;
}
const multihash = require('multihashes');
let buf = multihash.fromB58String(hash);
let digest = multihash.decode(buf).digest;
const buf = multihash.fromB58String(hash);
const digest = multihash.decode(buf).digest;
return '0x' + multihash.toHexString(digest);
}
function exit(code) {
export function exit(code: number) {
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 || {});
const outputToConsole = !options.silent;
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 (options.exitOnError) {
return exit();
return exit(code);
}
if (typeof callback === 'function') {
callback(`shell returned code ${code}`);
@ -113,56 +120,56 @@ function runCmd(cmd, options, callback) {
}
});
result.stdout.on('data', function(data) {
result.stdout.on('data', (data: any) => {
if (outputToConsole) {
console.log(data);
}
});
result.stderr.on('data', function(data) {
result.stderr.on('data', (data: any) => {
if (outputToConsole) {
console.log(data);
}
});
}
function copyToClipboard(text) {
export function copyToClipboard(text: string) {
clipboardy.writeSync(text);
}
function byName(a, b) {
export function byName(a, b) {
return a.name.localeCompare(b.name);
}
function isFolder(node) {
export function isFolder(node) {
return node.children && node.children.length;
}
function isNotFolder(node){
export function isNotFolder(node) {
return !isFolder(node);
}
function fileTreeSort(nodes){
export function fileTreeSort(nodes) {
const folders = nodes.filter(isFolder).sort(byName);
const files = nodes.filter(isNotFolder).sort(byName);
return folders.concat(files);
}
function proposeAlternative(word, _dictionary, _exceptions) {
export function proposeAlternative(word, _dictionary, _exceptions) {
const propose = require('propose');
let exceptions = _exceptions || [];
let dictionary = _dictionary.filter((entry) => {
const exceptions = _exceptions || [];
const dictionary = _dictionary.filter((entry) => {
return exceptions.indexOf(entry) < 0;
});
return propose(word, dictionary, {threshold: 0.3});
}
function toposort(graph) {
export function toposort(graph) {
return toposortGraph(graph);
}
function deconstructUrl(endpoint) {
export function deconstructUrl(endpoint) {
const matches = endpoint.match(/(wss?|https?):\/\/([a-zA-Z0-9_.\/-]*):?([0-9]*)?/);
return {
protocol: matches[1],
@ -172,7 +179,7 @@ function deconstructUrl(endpoint) {
};
}
function prepareContractsConfig(config) {
export function prepareContractsConfig(config) {
if (config.deploy) {
config.contracts = config.deploy;
delete config.deploy;
@ -213,7 +220,7 @@ function prepareContractsConfig(config) {
return config;
}
function jsonFunctionReplacer(_key, value) {
export function jsonFunctionReplacer(_key, value) {
if (typeof value === 'function') {
return value.toString();
}
@ -221,9 +228,11 @@ function jsonFunctionReplacer(_key, value) {
return value;
}
function fuzzySearch(text, list, filter) {
export function fuzzySearch(text, list, filter) {
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
* @returns {string} the constructued URL, with defaults
*/
function buildUrl(protocol, host, port, type) {
if (!host) throw new Error('utils.buildUrl: parameter \'host\' is required');
if (port) port = ':' + port;
else port = '';
export function buildUrl(protocol, host, port, type) {
if (!host) {
throw new Error('utils.buildUrl: parameter \'host\' is required');
}
if (port) {
port = ':' + port;
} else {
port = '';
}
if (!protocol) {
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.
* @returns {string} the constructued URL, with defaults
*/
function buildUrlFromConfig(configObj) {
if (!configObj) 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');
export function buildUrlFromConfig(configObj) {
if (!configObj) {
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);
}
function errorMessage(e) {
export function errorMessage(e) {
if (typeof e === 'string') {
return e;
} else if (e && e.message) {
@ -273,95 +291,10 @@ function errorMessage(e) {
return e;
}
function isConstructor(obj) {
export function isConstructor(obj) {
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);
}
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.
*/
class LogHandler {
export class LogHandler {
/**
* @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 { Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark";
import { Logger } from 'embark-logger';
import { performance, PerformanceObserver } from "perf_hooks";
import prettyMs from "pretty-ms";
import { last, recursiveMerge } from "./collections";

View File

@ -194,26 +194,6 @@ class Cmd {
}
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
.command('blockchain [environment]')
.option('-p, --port [port]', __('port to run the dev webserver (default: %s)', '8000'))

View File

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

View File

@ -1,5 +1,12 @@
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');

View File

@ -1,721 +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 configObject = {
"default": {
"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,310 +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');
// Default priority of actions with no specified priority. 1 => Highest
const DEFAULT_ACTION_PRIORITY = 50;
// 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, options, cb) {
if (typeof options === 'function') {
cb = options;
options = {};
}
if (!this.eventActions[eventName]) {
this.eventActions[eventName] = [];
}
this.eventActions[eventName].push({action: cb, options: Object.assign({priority: DEFAULT_ACTION_PRIORITY}, options)});
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,261 +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);
}
actionPlugins.sort((a, b) => {
const aPriority = a[0].options.priority;
const bPriority = b[0].options.priority;
if (aPriority < bPriority) {
return -1;
}
if (aPriority > bPriority) {
return 1;
}
return 0;
});
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.action.name, pluginName);
if (typeof (args) === 'function') {
plugin.action.call(plugin.action, (...params) => {
nextEach(...params || current_args);
});
} else {
plugin.action.call(plugin.action, 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;
const Logger = require('embark-logger');
let pkg = require('../../package.json');
import { Config, Events } from 'embark-core';
import { Logger } from 'embark-logger';
class Embark {
constructor(options) {
this.version = version;
this.version = pkg.version;
this.options = options || {};
}
initConfig(env, options) {
let Events = require('./core/events.js');
let Config = require('./core/config.js');
this.events = new Events();
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.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*/
import { TestLogger } from 'embark-core';
import * as i18n from 'embark-i18n';
const assert = require('assert');
const sinon = require('sinon');
let TestLogger = require('../lib/utils/test_logger');
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');
describe('embark.AccountParser', function () {

View File

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

View File

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

View File

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

View File

@ -1,12 +1,10 @@
/*global describe, it, require*/
import { Events, Plugins, TestLogger } from 'embark-core';
import { File, Types } from "embark-utils";
const assert = require('assert');
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) {
return new File({filename: file, type: Types.dappFile, path: file});

View File

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

View File

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

View File

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

View File

@ -1,10 +1,10 @@
/*global __dirname, describe, it, beforeEach, afterEach, require*/
import * as i18n from 'embark-i18n';
import { Plugins } from 'embark-core';
const {fakeEmbark} = require('embark-testing');
const assert = require('assert');
const sinon = require('sinon');
const Plugins = require('../lib/core/plugins');
i18n.setOrDetectLocale('en');
describe('embark.plugins', function() {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,8 @@
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 { AccountParser, dappPath } from "embark-utils";
import { Logger } from 'embark-logger';
import Web3 from "web3";
const { blockchain: blockchainConstants } = require("embark-core/constants");

View File

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

View File

@ -1,8 +1,8 @@
import "colors";
import { __ } from "embark-i18n";
import DebuggerManager from "./debugger_manager";
import 'colors';
import { __ } from 'embark-i18n';
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 {
on: any;
@ -31,28 +31,28 @@ class TransactionDebugger {
constructor(embark: EmbarkApi, options?: any) {
this.embark = embark;
this.debuggerManager = new DebuggerManager("http://localhost:8545");
embark.events.on("contracts:compile:solc", this.debuggerManager.setInputJson.bind(this.debuggerManager));
embark.events.on("contracts:compiled:solc", this.debuggerManager.setOutputJson.bind(this.debuggerManager));
this.debuggerManager = new DebuggerManager('http://localhost:8545');
embark.events.on('contracts:compile:solc', this.debuggerManager.setInputJson.bind(this.debuggerManager));
embark.events.on('contracts:compiled:solc', this.debuggerManager.setOutputJson.bind(this.debuggerManager));
this.txTracker = {};
this.lastTx = "";
this.lastTx = '';
this.isDebugging = false;
this.currentCmdTxHash = "";
this.currentCmdTxHash = '';
this.listenToEvents();
this.listenToCommands();
this.listentoAPI();
}
private listenToEvents() {
this.embark.events.on("blockchain:tx", (tx: any) => {
this.embark.events.request("contracts:contract", tx.name, (contract: any) => {
this.embark.events.on('blockchain:tx', (tx: any) => {
this.embark.events.request('contracts:contract', tx.name, (contract: any) => {
this.txTracker[tx.transactionHash] = {tx, contract};
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) => {
lines.forEach((errorLine: string) => {
@ -60,7 +60,7 @@ class TransactionDebugger {
});
this.findVarsInLine(tx.transactionHash, line, knownVars, (foundVars: any) => {
if (!foundVars) { return; }
this.embark.logger.info("vars:");
this.embark.logger.info('vars:');
foundVars.forEach((variable: any) => {
this.embark.logger.info(`${variable.name}: ${variable.value}`);
});
@ -84,7 +84,7 @@ class TransactionDebugger {
for (const variable of Object.keys(knownVars.locals || {})) {
const value: any = knownVars.locals[variable];
const variableName: string = variable.split(" ")[0];
const variableName: string = variable.split(' ')[0];
if (line && line.indexOf(variableName) >= 0) {
foundVars.push({name: variable, value});
}
@ -92,7 +92,7 @@ class TransactionDebugger {
for (const variable of Object.keys(knownVars.contract || {})) {
const value: any = knownVars.contract[variable];
const variableName: string = variable.split(" ")[0];
const variableName: string = variable.split(' ')[0];
if (line && line.indexOf(variableName) >= 0) {
foundVars.push({name: variable, value});
}
@ -106,10 +106,10 @@ class TransactionDebugger {
this.debuggerData = {};
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;
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) {
this.embark.logger.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.events.emit("stop");
this.apiDebugger.events.emit('stop');
this.apiDebugger = false;
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();
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();
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()) {
this.apiDebugger.stepOverForward(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()) {
this.apiDebugger.stepOverBack(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()) {
this.apiDebugger.stepIntoForward(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()) {
this.apiDebugger.stepIntoBack(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});
});
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; }
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.possibleSteps = {
canGoNext: this.apiDebugger.canGoNext(),
@ -193,7 +193,7 @@ class TransactionDebugger {
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.possibleSteps = {
canGoNext: this.apiDebugger.canGoNext(),
@ -202,7 +202,7 @@ class TransactionDebugger {
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.possibleSteps = {
canGoNext: this.apiDebugger.canGoNext(),
@ -227,27 +227,27 @@ class TransactionDebugger {
private listenToCommands() {
this.cmdDebugger = false;
this.currentCmdTxHash = "";
this.currentCmdTxHash = '';
const self = this;
function startDebug(txHash: string, filename: string, callback: (err?: string|object, output?: string) => void) {
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.displayStepInfo(callback);
});
}
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) => {
const [cmdName] = cmd.split(" ");
return cmdName === "debug";
const [cmdName] = cmd.split(' ');
return cmdName === 'debug';
},
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
const [_cmdName, txHash] = cmd.split(" ");
const [_cmdName, txHash] = cmd.split(' ');
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) {
this.embark.logger.error(err);
return callback();
@ -257,34 +257,34 @@ class TransactionDebugger {
});
return;
}
if (this.lastTx === "") {
return callback(undefined, __("No transaction to debug"));
if (this.lastTx === '') {
return callback(undefined, __('No transaction to debug'));
}
this.currentCmdTxHash = this.lastTx;
const filename: string = this.txTracker[this.lastTx].contract.filename;
startDebug(this.lastTx, filename, callback);
},
usage: "debug [txHash]",
usage: 'debug [txHash]',
});
this.embark.registerConsoleCommand({
description: __("Stops the active debugging session."),
matches: ["sd", "stop debugger"],
description: __('Stops the active debugging session.'),
matches: ['sd', 'stop debugger'],
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
if (!this.cmdDebugger) {
this.embark.logger.warn(NO_DEBUG_SESSION);
return callback();
}
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();
},
usage: " stop debugger/sd",
usage: ' stop debugger/sd',
});
this.embark.registerConsoleCommand({
description: __("Step over forward on the current debugging session"),
matches: ["next", "n"],
description: __('Step over forward on the current debugging session'),
matches: ['next', 'n'],
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
if (!this.cmdDebugger) {
this.embark.logger.warn(NO_DEBUG_SESSION);
@ -294,19 +294,19 @@ class TransactionDebugger {
return callback();
}
if (!this.cmdDebugger.currentStep()) {
this.embark.logger.info("end of execution reached");
this.embark.logger.info('end of execution reached');
this.cmdDebugger.unload();
return callback();
}
this.cmdDebugger.stepOverForward(true);
this.displayStepInfo(callback);
},
usage: " next/n",
usage: ' next/n',
});
this.embark.registerConsoleCommand({
description: __("Step over back on the current debugging session"),
matches: ["previous", "p"],
description: __('Step over back on the current debugging session'),
matches: ['previous', 'p'],
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
if (!this.cmdDebugger) {
this.embark.logger.warn(NO_DEBUG_SESSION);
@ -316,54 +316,54 @@ class TransactionDebugger {
return callback();
}
if (!this.cmdDebugger.currentStep()) {
this.embark.logger.info("end of execution reached");
this.embark.logger.info('end of execution reached');
return this.cmdDebugger.unload();
}
this.cmdDebugger.stepOverBack(true);
this.displayStepInfo(callback);
},
usage: " previous/p",
usage: ' previous/p',
});
this.embark.registerConsoleCommand({
description: __("Display local variables of the current debugging session"),
matches: ["var local", "v l", "vl"],
description: __('Display local variables of the current debugging session'),
matches: ['var local', 'v l', 'vl'],
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
if (!this.cmdDebugger) {
this.embark.logger.warn(NO_DEBUG_SESSION);
return callback();
}
this.embark.logger.info("Locals:");
this.embark.logger.info('Locals:');
const debugVars = this.simplifyDebuggerVars(this.cmdDebugger.solidityLocals);
for (const debugVar of Object.keys(debugVars)) {
this.embark.logger.info(`${debugVar}: ` + `${debugVars[debugVar]}`.white);
}
callback();
},
usage: " var local/v l/vl",
usage: ' var local/v l/vl',
});
this.embark.registerConsoleCommand({
description: __("Display global variables of the current debugging session"),
matches: ["var global", "v g", "vg"],
description: __('Display global variables of the current debugging session'),
matches: ['var global', 'v g', 'vg'],
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
if (!this.cmdDebugger) {
this.embark.logger.warn(NO_DEBUG_SESSION);
return callback();
}
this.embark.logger.info("Globals:");
this.embark.logger.info('Globals:');
const debugVars = this.simplifyDebuggerVars(this.cmdDebugger.solidityState);
for (const debugVar of Object.keys(debugVars)) {
this.embark.logger.info(`${debugVar}: ` + `${debugVars[debugVar]}`.white);
}
callback();
},
usage: " var global/v g/vg",
usage: ' var global/v g/vg',
});
this.embark.registerConsoleCommand({
description: __("Display solidity global variables of the current debugging session"),
matches: ["var all", "v a", "va"],
description: __('Display solidity global variables of the current debugging session'),
matches: ['var all', 'v a', 'va'],
process: (cmd: string, callback: (err?: string|object, output?: string) => void) => {
if (!this.cmdDebugger) {
this.embark.logger.warn(NO_DEBUG_SESSION);
@ -374,37 +374,37 @@ class TransactionDebugger {
this.embark.logger.error(err);
return callback();
}
this.embark.logger.info("Solidity Global Variables:");
this.embark.logger.info('Solidity Global Variables:');
for (const debugVar of Object.keys(globals)) {
this.embark.logger.info(`${debugVar}: ` + `${globals[debugVar]}`.white);
}
callback();
});
},
usage: " var all/v a/va",
usage: ' var all/v a/va',
});
}
private getGlobals(txHash: string, cb: 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); }
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); }
/* tslint:disable:no-string-literal */
globals["block.blockHash"] = tx.blockHash;
globals["block.number"] = tx.blockNumber;
globals["block.coinbase"] = block.miner;
globals["block.difficulty"] = block.difficulty;
globals["block.gaslimit"] = block.gasLimit;
globals["block.timestamp"] = block.timestamp;
globals["msg.sender"] = tx.from;
globals["msg.gas"] = tx.gas;
globals["msg.gasPrice"] = tx.gasPrice;
globals["msg.value"] = tx.value;
globals["now"] = block.timestamp;
globals['block.blockHash'] = tx.blockHash;
globals['block.number'] = tx.blockNumber;
globals['block.coinbase'] = block.miner;
globals['block.difficulty'] = block.difficulty;
globals['block.gaslimit'] = block.gasLimit;
globals['block.timestamp'] = block.timestamp;
globals['msg.sender'] = tx.from;
globals['msg.gas'] = tx.gas;
globals['msg.gasPrice'] = tx.gasPrice;
globals['msg.value'] = tx.value;
globals['now'] = block.timestamp;
/* tslint:enable:no-string-literal */
cb(null, globals);
@ -414,24 +414,24 @@ class TransactionDebugger {
private displayPossibleActions() {
const actions: string[] = [];
actions.push("actions: ");
actions.push('actions: ');
if (this.cmdDebugger.canGoPrevious()) {
actions.push("(p)revious");
actions.push('(p)revious');
}
if (this.cmdDebugger.canGoNext()) {
actions.push("(n)ext");
actions.push('(n)ext');
}
actions.push("(vl) var local");
actions.push("(vg) var global");
actions.push("(va) var all");
actions.push("(sd) stop debugger");
actions.push('(vl) var local');
actions.push('(vg) var global');
actions.push('(va) var all');
actions.push('(sd) stop debugger');
if (actions.length === 1) { return; }
this.embark.logger.info("");
this.embark.logger.info(actions.join(" | "));
this.embark.logger.info('');
this.embark.logger.info(actions.join(' | '));
}
private displayVarsInLine(cb?: any) {
@ -450,7 +450,7 @@ class TransactionDebugger {
if (!foundVars) {
return cb ? cb() : null;
}
this.embark.logger.info("vars:");
this.embark.logger.info('vars:');
foundVars.forEach((variable: any) => {
this.embark.logger.info(`${variable.name}: ` + `${variable.value}`.white);
});

View File

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

View File

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

View File

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

View File

@ -10,7 +10,7 @@ const WhisperGethClient = require('./whisperClient.js');
import { IPC } from 'embark-core';
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)
const IPC_CONNECT_INTERVAL = 2000;

View File

@ -10,7 +10,7 @@ const ParityClient = require('./parityClient.js');
import {IPC} from 'embark-core';
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)
const IPC_CONNECT_INTERVAL = 2000;

View File

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

View File

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

View File

@ -1,5 +1,5 @@
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 { schema } from "./schema";
const fs = require("fs");

View File

@ -48,7 +48,8 @@
"core-js": "3.3.5",
"embark-core": "^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": {
"@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 {
private embark: Embark;
private logger: Logger;

View File

@ -53,6 +53,7 @@
"embark-core": "^5.0.0-alpha.1",
"embark-i18n": "^5.0.0-alpha.1",
"embark-utils": "^5.0.0-alpha.1",
"embark-logger": "^5.0.0-alpha.1",
"web3": "1.2.1"
},
"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");
import { ABIDefinition } from "web3/eth/abi";

View File

@ -51,6 +51,7 @@
"embark-core": "^5.0.0-alpha.1",
"embark-i18n": "^5.0.0-alpha.1",
"embark-utils": "^5.0.0-alpha.1",
"embark-logger": "^5.0.0-alpha.1",
"express": "4.17.1",
"express-ws": "4.0.0",
"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 { buildUrl, findNextPort } from "embark-utils";
import { Logger } from 'embark-logger';
import { Proxy } from "./proxy";
const constants = require("embark-core/constants");

View File

@ -44,6 +44,8 @@
"@babel/core": "7.6.4",
"@babel/plugin-proposal-class-properties": "7.5.5",
"@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-optional-chaining": "7.6.0",
"@babel/plugin-syntax-dynamic-import": "7.2.0",

View File

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

View File

@ -5,13 +5,20 @@
],
"jsRules": {},
"rules": {
"arrow-parens": false,
"interface-name": [true, "never-prefix"],
"max-line-length": [true, 200],
"member-ordering": [false],
"member-access": false,
"no-empty": false,
"no-console": 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": []
}

View File

@ -405,6 +405,22 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-dynamic-import" "^7.2.0"
"@babel/plugin-proposal-export-default-from@7.5.2":
version "7.5.2"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.5.2.tgz#2c0ac2dcc36e3b2443fead2c3c5fc796fb1b5145"
integrity sha512-wr9Itk05L1/wyyZKVEmXWCdcsp/e185WUNl6AfYZeEKYaUPPvHXRDqO5K1VH7/UamYqGJowFRuCv30aDYZawsg==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-export-default-from" "^7.2.0"
"@babel/plugin-proposal-export-namespace-from@7.5.2":
version "7.5.2"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.5.2.tgz#ccd5ed05b06d700688ff1db01a9dd27155e0d2a0"
integrity sha512-TKUdOL07anjZEbR1iSxb5WFh810KyObdd29XLFLGo1IDsSuGrjH3ouWSbAxHNmrVKzr9X71UYl2dQ7oGGcRp0g==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-export-namespace-from" "^7.2.0"
"@babel/plugin-proposal-json-strings@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317"
@ -492,6 +508,20 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-export-default-from@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.2.0.tgz#edd83b7adc2e0d059e2467ca96c650ab6d2f3820"
integrity sha512-c7nqUnNST97BWPtoe+Ssi+fJukc9P9/JMZ71IOMNQWza2E+Psrd46N6AEvtw6pqK+gt7ChjXyrw4SPDO79f3Lw==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-export-namespace-from@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.2.0.tgz#8d257838c6b3b779db52c0224443459bd27fb039"
integrity sha512-1zGA3UNch6A+A11nIzBVEaE3DDJbjfB+eLIcf0GGOh/BJr/8NxL3546MGhV/r0RhH4xADFIEso39TKCfEMlsGA==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-flow@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.2.0.tgz#a765f061f803bc48f240c26f8747faf97c26bf7c"
@ -17865,7 +17895,6 @@ scrypt-js@2.0.4:
"scrypt-shim@github:web3-js/scrypt-shim":
version "0.1.0"
uid be5e616323a8b5e568788bf94d03c1b8410eac54
resolved "https://codeload.github.com/web3-js/scrypt-shim/tar.gz/be5e616323a8b5e568788bf94d03c1b8410eac54"
dependencies:
scryptsy "^2.1.0"