From d2556af8ba3f70e11151fa99784ff5fc2503582f Mon Sep 17 00:00:00 2001 From: Pascal Precht Date: Mon, 11 Nov 2019 14:41:40 +0100 Subject: [PATCH] refactor(@embark/core): move Engine into embark-core --- babel.config.js | 2 + packages/core/code-runner/package.json | 2 + packages/core/code-runner/src/index.ts | 4 +- packages/core/code-runner/src/vm.ts | 3 +- packages/core/console/src/lib/index.ts | 6 +- packages/core/console/src/test/console.js | 2 +- packages/core/core/package.json | 25 +- packages/core/core/src/config.ts | 758 ++++++++++++++++++ .../core/src/configDefaults.ts} | 16 +- .../engine.js => core/core/src/engine.ts} | 158 +++- .../events.js => core/core/src/events.ts} | 54 +- packages/core/core/src/fs.ts | 93 +++ packages/core/core/src/index.js | 5 - packages/core/core/src/index.ts | 14 + packages/core/core/src/plugin.ts | 370 +++++++++ packages/core/core/src/plugins.ts | 284 +++++++ packages/core/core/src/services_monitor.ts | 103 +++ .../lib => core/core/src}/utils/debug_util.js | 0 .../core/src}/utils/template_generator.js | 28 +- .../core/src}/utils/test_logger.js | 4 +- packages/core/core/src/utils/utils.js | 9 + packages/core/core/tsconfig.json | 5 + packages/core/core/tslint.json | 4 + packages/core/i18n/index.d.ts | 6 +- packages/core/i18n/src/index.ts | 24 +- packages/core/logger/src/index.js | 4 +- packages/core/typings/index.d.ts | 20 +- packages/core/typings/src/contract.d.ts | 2 +- packages/core/typings/src/embark.d.ts | 4 +- packages/core/typings/src/plugins.d.ts | 2 +- .../src/prettier-plugin-solidity/index.d.ts | 2 +- .../src/remix-debug-debugtest/index.d.ts | 2 +- packages/core/utils/{index.d.ts => foo.d.ts} | 2 + packages/core/utils/package.json | 1 + packages/core/utils/src/accountParser.js | 4 +- packages/core/utils/src/addressUtils.ts | 2 +- packages/core/utils/src/collections.ts | 2 +- packages/core/utils/src/file.ts | 80 +- packages/core/utils/src/host.ts | 18 +- .../core/utils/src/{index.js => index.ts} | 221 ++--- packages/core/utils/src/logHandler.js | 4 +- .../core/utils/src/longRunningProcessTimer.ts | 2 +- packages/embark/src/cmd/cmd.js | 20 - packages/embark/src/cmd/cmd_controller.js | 55 +- .../embark/src/cmd/dashboard/dashboard.js | 9 +- packages/embark/src/lib/core/config.js | 721 ----------------- packages/embark/src/lib/core/fs.js | 127 --- packages/embark/src/lib/core/plugin.js | 310 ------- packages/embark/src/lib/core/plugins.js | 261 ------ .../embark/src/lib/core/services_monitor.js | 92 --- packages/embark/src/lib/index.js | 19 +- packages/embark/src/lib/utils/utils.js | 116 --- packages/embark/src/test/accountParser.js | 13 +- packages/embark/src/test/config.js | 5 +- packages/embark/src/test/contracts.js | 9 +- packages/embark/src/test/events.js | 3 +- .../src/test/modules/compiler/compiler.js | 4 +- .../test/modules/console_listener.js.disabled | 6 +- .../src/test/modules/solidity/remapImports.js | 1 - .../src/test/modules/solidity/solidity.js | 4 +- packages/embark/src/test/plugins.spec.js | 2 +- packages/embark/src/test/processLauncher.js | 3 +- packages/embark/src/test/template.js | 2 +- packages/embark/src/test/utils.js | 1 - packages/embark/src/test/vm.js | 2 +- .../plugins/accounts-manager/package.json | 1 + .../plugins/accounts-manager/src/index.ts | 3 +- .../plugins/debugger/src/debugger_manager.ts | 16 +- packages/plugins/debugger/src/index.ts | 178 ++-- packages/plugins/deploy-tracker/package.json | 1 + .../src/test/deploymentChecksSpec.js | 2 +- .../src/test/trackingFunctionsSpec.js | 2 +- packages/plugins/geth/src/blockchain.js | 2 +- packages/plugins/parity/src/blockchain.js | 2 +- packages/plugins/scaffolding/package.json | 1 + .../plugins/scaffolding/src/commandOptions.ts | 2 +- .../scaffolding/src/smartContractsRecipe.ts | 2 +- packages/stack/blockchain/package.json | 3 +- packages/stack/blockchain/src/api.ts | 3 +- packages/stack/contracts-manager/package.json | 1 + .../stack/contracts-manager/src/contract.ts | 3 +- packages/stack/proxy/package.json | 1 + packages/stack/proxy/src/index.ts | 5 +- packages/utils/collective/package.json | 2 + tsconfig.json | 1 + tslint.json | 9 +- yarn.lock | 31 +- 87 files changed, 2249 insertions(+), 2158 deletions(-) create mode 100644 packages/core/core/src/config.ts rename packages/{embark/src/lib/core/configDefaults.js => core/core/src/configDefaults.ts} (83%) rename packages/{embark/src/lib/core/engine.js => core/core/src/engine.ts} (71%) rename packages/{embark/src/lib/core/events.js => core/core/src/events.ts} (86%) create mode 100644 packages/core/core/src/fs.ts delete mode 100644 packages/core/core/src/index.js create mode 100644 packages/core/core/src/index.ts create mode 100644 packages/core/core/src/plugin.ts create mode 100644 packages/core/core/src/plugins.ts create mode 100644 packages/core/core/src/services_monitor.ts rename packages/{embark/src/lib => core/core/src}/utils/debug_util.js (100%) rename packages/{embark/src/lib => core/core/src}/utils/template_generator.js (94%) rename packages/{embark/src/lib => core/core/src}/utils/test_logger.js (95%) create mode 100644 packages/core/core/src/utils/utils.js create mode 100644 packages/core/core/tsconfig.json create mode 100644 packages/core/core/tslint.json rename packages/core/utils/{index.d.ts => foo.d.ts} (95%) rename packages/core/utils/src/{index.js => index.ts} (59%) delete mode 100644 packages/embark/src/lib/core/config.js delete mode 100644 packages/embark/src/lib/core/fs.js delete mode 100644 packages/embark/src/lib/core/plugin.js delete mode 100644 packages/embark/src/lib/core/plugins.js delete mode 100644 packages/embark/src/lib/core/services_monitor.js delete mode 100644 packages/embark/src/lib/utils/utils.js diff --git a/babel.config.js b/babel.config.js index f62a82cdb..4143fbf09 100644 --- a/babel.config.js +++ b/babel.config.js @@ -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 diff --git a/packages/core/code-runner/package.json b/packages/core/code-runner/package.json index 843f51c4e..6a4e587b8 100644 --- a/packages/core/code-runner/package.json +++ b/packages/core/code-runner/package.json @@ -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", diff --git a/packages/core/code-runner/src/index.ts b/packages/core/code-runner/src/index.ts index 783360ebe..5c626ed02 100644 --- a/packages/core/code-runner/src/index.ts +++ b/packages/core/code-runner/src/index.ts @@ -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; diff --git a/packages/core/code-runner/src/vm.ts b/packages/core/code-runner/src/vm.ts index 4e8022030..b652d24cd 100644 --- a/packages/core/code-runner/src/vm.ts +++ b/packages/core/code-runner/src/vm.ts @@ -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"; diff --git a/packages/core/console/src/lib/index.ts b/packages/core/console/src/lib/index.ts index 57fdc8d08..1c6d72d9a 100644 --- a/packages/core/console/src/lib/index.ts +++ b/packages/core/console/src/lib/index.ts @@ -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({ diff --git a/packages/core/console/src/test/console.js b/packages/core/console/src/test/console.js index eed3cc7a4..369231c1f 100644 --- a/packages/core/console/src/test/console.js +++ b/packages/core/console/src/test/console.js @@ -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'; diff --git a/packages/core/core/package.json b/packages/core/core/package.json index 2058cc2b4..27d16bbff 100644 --- a/packages/core/core/package.json +++ b/packages/core/core/package.json @@ -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", diff --git a/packages/core/core/src/config.ts b/packages/core/core/src/config.ts new file mode 100644 index 000000000..b8afa0775 --- /dev/null +++ b/packages/core/core/src/config.ts @@ -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); +} diff --git a/packages/embark/src/lib/core/configDefaults.js b/packages/core/core/src/configDefaults.ts similarity index 83% rename from packages/embark/src/lib/core/configDefaults.js rename to packages/core/core/src/configDefaults.ts index 46aa9a8f2..445b1e7f8 100644 --- a/packages/embark/src/lib/core/configDefaults.js +++ b/packages/core/core/src/configDefaults.ts @@ -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: { } } }; diff --git a/packages/embark/src/lib/core/engine.js b/packages/core/core/src/engine.ts similarity index 71% rename from packages/embark/src/lib/core/engine.js rename to packages/core/core/src/engine.ts index 77387d983..bf1062c79 100644 --- a/packages/embark/src/lib/core/engine.js +++ b/packages/core/core/src/engine.ts @@ -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'); + callback = callback || function() {}; - 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,28 +106,36 @@ class Engine { } startEngine(cb) { - this.plugins.emitAndRunActionsForEvent("embark:engine:started", {}, (err) => { - if (err) { - console.error("error starting engine"); - console.error(err); - process.exit(1); - } + if (this.plugins) { + this.plugins.emitAndRunActionsForEvent("embark:engine:started", {}, (err) => { + if (err) { + console.error("error starting engine"); + console.error(err); + process.exit(1); + } + cb(); + }); + } else { cb(); - }); + } } registerModule(moduleName, options) { - this.plugins.loadInternalPlugin(moduleName, options || {}); + if (this.plugins) { + this.plugins.loadInternalPlugin(moduleName, options || {}); + } } - registerModulePackage(moduleName, options) { - return this.plugins.loadInternalPlugin(moduleName, options || {}, true); + 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,14 +153,14 @@ class Engine { cockpit: this.cockpitModules }; - let group = groups[groupName]; + const group = groups[groupName]; if (!group) { throw new Error("unknown service: " + groupName); } // need to be careful with circular references due to passing the web3 object - //this.logger.trace("calling: " + serviceName + "(" + JSON.stringify(options) + ")"); + // this.logger.trace("calling: " + serviceName + "(" + JSON.stringify(options) + ")"); return group.apply(this, [options]); } @@ -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}); - this.servicesMonitor.addCheck('Embark', (cb) => { - return cb({name: 'Embark ' + this.version, status: 'on'}); - }, 0); - let plugin = this.plugins.createPlugin('coreservicesplugin', {}); - plugin.registerActionForEvent("embark:engine:started", (_params, cb) => { - this.servicesMonitor.startMonitor(); - cb(); - }); + if (this.servicesMonitor) { + this.servicesMonitor.addCheck('Embark', (cb) => { + return cb({name: 'Embark ' + this.version, status: 'on'}); + }, 0); + + if (this.plugins) { + const plugin = this.plugins.createPlugin('coreservicesplugin', {}); + plugin.registerActionForEvent("embark:engine:started", (_params, cb) => { + this.servicesMonitor && this.servicesMonitor.startMonitor(); + cb(); + }); + } + } + this.registerModulePackage('embark-code-runner', {ipc: this.ipc}); // 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)); + }; +} diff --git a/packages/embark/src/lib/core/events.js b/packages/core/core/src/events.ts similarity index 86% rename from packages/embark/src/lib/core/events.js rename to packages/core/core/src/events.ts index a69d0e19a..be33e4c60 100644 --- a/packages/embark/src/lib/core/events.js +++ b/packages/core/core/src/events.ts @@ -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(); - origin = origin.split("(")[0].trim(); - return origin; + 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(); - origin = origin.split("(")[0].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); @@ -160,7 +166,7 @@ EmbarkEmitter.prototype.request = function() { // if we don't have a command handler set for this event yet, // store it and fire it once a command handler is set if (!this.listeners(listenerName).length) { - if(!toFire[listenerName]) { + if (!toFire[listenerName]) { toFire[listenerName] = []; } toFire[listenerName].push(other_args); @@ -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; diff --git a/packages/core/core/src/fs.ts b/packages/core/core/src/fs.ts new file mode 100644 index 000000000..f205bc1f9 --- /dev/null +++ b/packages/core/core/src/fs.ts @@ -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); } diff --git a/packages/core/core/src/index.js b/packages/core/core/src/index.js deleted file mode 100644 index 11d96aec9..000000000 --- a/packages/core/core/src/index.js +++ /dev/null @@ -1,5 +0,0 @@ -export { ProcessLauncher } from './processes/processLauncher'; -export { ProcessManager } from './processes/processManager'; -export { ProcessWrapper } from './processes/processWrapper'; - -export { IPC } from './ipc'; diff --git a/packages/core/core/src/index.ts b/packages/core/core/src/index.ts new file mode 100644 index 000000000..dd6a190cc --- /dev/null +++ b/packages/core/core/src/index.ts @@ -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 }; diff --git a/packages/core/core/src/plugin.ts b/packages/core/core/src/plugin.ts new file mode 100644 index 000000000..bcda6474d --- /dev/null +++ b/packages/core/core/src/plugin.ts @@ -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; + } +} diff --git a/packages/core/core/src/plugins.ts b/packages/core/core/src/plugins.ts new file mode 100644 index 000000000..91f4bf473 --- /dev/null +++ b/packages/core/core/src/plugins.ts @@ -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); + } +} diff --git a/packages/core/core/src/services_monitor.ts b/packages/core/core/src/services_monitor.ts new file mode 100644 index 000000000..aea3beb9a --- /dev/null +++ b/packages/core/core/src/services_monitor.ts @@ -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); + } + }); + } +} diff --git a/packages/embark/src/lib/utils/debug_util.js b/packages/core/core/src/utils/debug_util.js similarity index 100% rename from packages/embark/src/lib/utils/debug_util.js rename to packages/core/core/src/utils/debug_util.js diff --git a/packages/embark/src/lib/utils/template_generator.js b/packages/core/core/src/utils/template_generator.js similarity index 94% rename from packages/embark/src/lib/utils/template_generator.js rename to packages/core/core/src/utils/template_generator.js index c3baad1e1..66c8f2e7d 100644 --- a/packages/embark/src/lib/utils/template_generator.js +++ b/packages/core/core/src/utils/template_generator.js @@ -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(); + }); +} diff --git a/packages/embark/src/lib/utils/test_logger.js b/packages/core/core/src/utils/test_logger.js similarity index 95% rename from packages/embark/src/lib/utils/test_logger.js rename to packages/core/core/src/utils/test_logger.js index 165d20b38..e94a651f9 100644 --- a/packages/embark/src/lib/utils/test_logger.js +++ b/packages/core/core/src/utils/test_logger.js @@ -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; diff --git a/packages/core/core/src/utils/utils.js b/packages/core/core/src/utils/utils.js new file mode 100644 index 000000000..2a58aef01 --- /dev/null +++ b/packages/core/core/src/utils/utils.js @@ -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); +} diff --git a/packages/core/core/tsconfig.json b/packages/core/core/tsconfig.json new file mode 100644 index 000000000..1dc6632e6 --- /dev/null +++ b/packages/core/core/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../../tsconfig.json", + "include": ["src/**/*"] +} + diff --git a/packages/core/core/tslint.json b/packages/core/core/tslint.json new file mode 100644 index 000000000..1bdfa34f9 --- /dev/null +++ b/packages/core/core/tslint.json @@ -0,0 +1,4 @@ +{ + "extends": "../../../tslint.json" +} + diff --git a/packages/core/i18n/index.d.ts b/packages/core/i18n/index.d.ts index c567eb862..6e35ad128 100644 --- a/packages/core/i18n/index.d.ts +++ b/packages/core/i18n/index.d.ts @@ -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): void; function __( phraseOrOptions: string | i18n.TranslateOptions, diff --git a/packages/core/i18n/src/index.ts b/packages/core/i18n/src/index.ts index 1580b0b9b..1a497abce 100644 --- a/packages/core/i18n/src/index.ts +++ b/packages/core/i18n/src/index.ts @@ -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, diff --git a/packages/core/logger/src/index.js b/packages/core/logger/src/index.js index deb7d34b4..5f7240284 100644 --- a/packages/core/logger/src/index.js +++ b/packages/core/logger/src/index.js @@ -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; diff --git a/packages/core/typings/index.d.ts b/packages/core/typings/index.d.ts index 3dae9dc88..e918b9020 100644 --- a/packages/core/typings/index.d.ts +++ b/packages/core/typings/index.d.ts @@ -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'; diff --git a/packages/core/typings/src/contract.d.ts b/packages/core/typings/src/contract.d.ts index f56c9f06d..fa3041afb 100644 --- a/packages/core/typings/src/contract.d.ts +++ b/packages/core/typings/src/contract.d.ts @@ -1,4 +1,4 @@ -import { ABIDefinition } from "web3/eth/abi"; +import { ABIDefinition } from 'web3/eth/abi'; export interface Contract { abiDefinition: ABIDefinition[]; diff --git a/packages/core/typings/src/embark.d.ts b/packages/core/typings/src/embark.d.ts index 662083353..69a053b35 100644 --- a/packages/core/typings/src/embark.d.ts +++ b/packages/core/typings/src/embark.d.ts @@ -1,5 +1,5 @@ -import { Logger } from "./logger"; -import { Plugins } from "./plugins"; +import { Logger } from './logger'; +import { Plugins } from './plugins'; type CommandCallback = ( opt1?: any, diff --git a/packages/core/typings/src/plugins.d.ts b/packages/core/typings/src/plugins.d.ts index 1cf4061d0..d417f5dc1 100644 --- a/packages/core/typings/src/plugins.d.ts +++ b/packages/core/typings/src/plugins.d.ts @@ -1,4 +1,4 @@ -import {Callback} from "./callbacks"; +import {Callback} from './callbacks'; export interface Plugin { dappGenerators: any; diff --git a/packages/core/typings/src/prettier-plugin-solidity/index.d.ts b/packages/core/typings/src/prettier-plugin-solidity/index.d.ts index 12ea8e2ce..09f21d221 100644 --- a/packages/core/typings/src/prettier-plugin-solidity/index.d.ts +++ b/packages/core/typings/src/prettier-plugin-solidity/index.d.ts @@ -1 +1 @@ -declare module "prettier-plugin-solidity"; +declare module 'prettier-plugin-solidity'; diff --git a/packages/core/typings/src/remix-debug-debugtest/index.d.ts b/packages/core/typings/src/remix-debug-debugtest/index.d.ts index 95f9c1732..8ac57156c 100644 --- a/packages/core/typings/src/remix-debug-debugtest/index.d.ts +++ b/packages/core/typings/src/remix-debug-debugtest/index.d.ts @@ -1 +1 @@ -declare module "remix-debug-debugtest"; +declare module 'remix-debug-debugtest'; diff --git a/packages/core/utils/index.d.ts b/packages/core/utils/foo.d.ts similarity index 95% rename from packages/core/utils/index.d.ts rename to packages/core/utils/foo.d.ts index 7d17f532c..aa0d5a583 100644 --- a/packages/core/utils/index.d.ts +++ b/packages/core/utils/foo.d.ts @@ -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; diff --git a/packages/core/utils/package.json b/packages/core/utils/package.json index 9d4914b97..4435cf914 100644 --- a/packages/core/utils/package.json +++ b/packages/core/utils/package.json @@ -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", diff --git a/packages/core/utils/src/accountParser.js b/packages/core/utils/src/accountParser.js index 5d8d580b4..0413a5abd 100644 --- a/packages/core/utils/src/accountParser.js +++ b/packages/core/utils/src/accountParser.js @@ -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; diff --git a/packages/core/utils/src/addressUtils.ts b/packages/core/utils/src/addressUtils.ts index 9c9b6694c..771b9bd86 100644 --- a/packages/core/utils/src/addressUtils.ts +++ b/packages/core/utils/src/addressUtils.ts @@ -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) { diff --git a/packages/core/utils/src/collections.ts b/packages/core/utils/src/collections.ts index 8c76e3bbc..ffe7a48e5 100644 --- a/packages/core/utils/src/collections.ts +++ b/packages/core/utils/src/collections.ts @@ -1,4 +1,4 @@ -const merge = require("merge"); +const merge = require('merge'); export function last(array: any) { return array[array.length - 1]; diff --git a/packages/core/utils/src/file.ts b/packages/core/utils/src/file.ts index 2050d2018..4cc95105c 100644 --- a/packages/core/utils/src/file.ts +++ b/packages/core/utils/src/file.ts @@ -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((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, }; } diff --git a/packages/core/utils/src/host.ts b/packages/core/utils/src/host.ts index c9b96a23a..283fc38a7 100644 --- a/packages/core/utils/src/host.ts +++ b/packages/core/utils/src/host.ts @@ -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); diff --git a/packages/core/utils/src/index.js b/packages/core/utils/src/index.ts similarity index 59% rename from packages/core/utils/src/index.js rename to packages/core/utils/src/index.ts index 3719eccc0..95ec3b736 100644 --- a/packages/core/utils/src/index.js +++ b/packages/core/utils/src/index.ts @@ -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,84 +92,84 @@ 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) { - if(code !== 0) { + const result = shelljs.exec(cmd, options, (code, stdout: string) => { + if (code !== 0) { if (options.exitOnError) { - return exit(); + return exit(code); } - if(typeof callback === 'function') { + if (typeof callback === 'function') { callback(`shell returned code ${code}`); } } else { - if(typeof callback === 'function') { + if (typeof callback === 'function') { return callback(null, stdout); } } }); - result.stdout.on('data', function(data) { - if(outputToConsole) { + 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; diff --git a/packages/core/utils/src/logHandler.js b/packages/core/utils/src/logHandler.js index cadb15871..22017731a 100644 --- a/packages/core/utils/src/logHandler.js +++ b/packages/core/utils/src/logHandler.js @@ -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; diff --git a/packages/core/utils/src/longRunningProcessTimer.ts b/packages/core/utils/src/longRunningProcessTimer.ts index 15a274115..a85ed1a2f 100644 --- a/packages/core/utils/src/longRunningProcessTimer.ts +++ b/packages/core/utils/src/longRunningProcessTimer.ts @@ -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"; diff --git a/packages/embark/src/cmd/cmd.js b/packages/embark/src/cmd/cmd.js index b914b2a61..194caaae2 100644 --- a/packages/embark/src/cmd/cmd.js +++ b/packages/embark/src/cmd/cmd.js @@ -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')) diff --git a/packages/embark/src/cmd/cmd_controller.js b/packages/embark/src/cmd/cmd_controller.js index b9affaff0..b04981693 100644 --- a/packages/embark/src/cmd/cmd_controller.js +++ b/packages/embark/src/cmd/cmd_controller.js @@ -1,20 +1,22 @@ -import {__} from 'embark-i18n'; -import {dappPath, embarkPath} from 'embark-utils'; +import { Config, Engine, Events, fs, TemplateGenerator } from 'embark-core'; +import { __ } from 'embark-i18n'; +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) { diff --git a/packages/embark/src/cmd/dashboard/dashboard.js b/packages/embark/src/cmd/dashboard/dashboard.js index 09ab719bd..b0ae2c435 100644 --- a/packages/embark/src/cmd/dashboard/dashboard.js +++ b/packages/embark/src/cmd/dashboard/dashboard.js @@ -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'); diff --git a/packages/embark/src/lib/core/config.js b/packages/embark/src/lib/core/config.js deleted file mode 100644 index cdf4226ec..000000000 --- a/packages/embark/src/lib/core/config.js +++ /dev/null @@ -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; diff --git a/packages/embark/src/lib/core/fs.js b/packages/embark/src/lib/core/fs.js deleted file mode 100644 index 64feb4ca0..000000000 --- a/packages/embark/src/lib/core/fs.js +++ /dev/null @@ -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 -}; diff --git a/packages/embark/src/lib/core/plugin.js b/packages/embark/src/lib/core/plugin.js deleted file mode 100644 index b8a1d8059..000000000 --- a/packages/embark/src/lib/core/plugin.js +++ /dev/null @@ -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; diff --git a/packages/embark/src/lib/core/plugins.js b/packages/embark/src/lib/core/plugins.js deleted file mode 100644 index bcf99f8dd..000000000 --- a/packages/embark/src/lib/core/plugins.js +++ /dev/null @@ -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; diff --git a/packages/embark/src/lib/core/services_monitor.js b/packages/embark/src/lib/core/services_monitor.js deleted file mode 100644 index 58b45675e..000000000 --- a/packages/embark/src/lib/core/services_monitor.js +++ /dev/null @@ -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; diff --git a/packages/embark/src/lib/index.js b/packages/embark/src/lib/index.js index e2843cd26..726002668 100644 --- a/packages/embark/src/lib/index.js +++ b/packages/embark/src/lib/index.js @@ -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; } diff --git a/packages/embark/src/lib/utils/utils.js b/packages/embark/src/lib/utils/utils.js deleted file mode 100644 index 9f2ffa74e..000000000 --- a/packages/embark/src/lib/utils/utils.js +++ /dev/null @@ -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 -}; diff --git a/packages/embark/src/test/accountParser.js b/packages/embark/src/test/accountParser.js index 9cb02e6f8..523c035bd 100644 --- a/packages/embark/src/test/accountParser.js +++ b/packages/embark/src/test/accountParser.js @@ -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 () { diff --git a/packages/embark/src/test/config.js b/packages/embark/src/test/config.js index 394cbe347..dd521b7c1 100644 --- a/packages/embark/src/test/config.js +++ b/packages/embark/src/test/config.js @@ -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({ diff --git a/packages/embark/src/test/contracts.js b/packages/embark/src/test/contracts.js index 5441891be..41fd151c9 100644 --- a/packages/embark/src/test/contracts.js +++ b/packages/embark/src/test/contracts.js @@ -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}); }; diff --git a/packages/embark/src/test/events.js b/packages/embark/src/test/events.js index b6e2dc6e0..e82ec430b 100644 --- a/packages/embark/src/test/events.js +++ b/packages/embark/src/test/events.js @@ -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"; diff --git a/packages/embark/src/test/modules/compiler/compiler.js b/packages/embark/src/test/modules/compiler/compiler.js index d2a772a9a..1f3025b26 100644 --- a/packages/embark/src/test/modules/compiler/compiler.js +++ b/packages/embark/src/test/modules/compiler/compiler.js @@ -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}); diff --git a/packages/embark/src/test/modules/console_listener.js.disabled b/packages/embark/src/test/modules/console_listener.js.disabled index bd7a5459c..547eda695 100644 --- a/packages/embark/src/test/modules/console_listener.js.disabled +++ b/packages/embark/src/test/modules/console_listener.js.disabled @@ -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, diff --git a/packages/embark/src/test/modules/solidity/remapImports.js b/packages/embark/src/test/modules/solidity/remapImports.js index 63f213d8d..bf1a3a453 100644 --- a/packages/embark/src/test/modules/solidity/remapImports.js +++ b/packages/embark/src/test/modules/solidity/remapImports.js @@ -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; diff --git a/packages/embark/src/test/modules/solidity/solidity.js b/packages/embark/src/test/modules/solidity/solidity.js index 051776862..ea5bb77e4 100644 --- a/packages/embark/src/test/modules/solidity/solidity.js +++ b/packages/embark/src/test/modules/solidity/solidity.js @@ -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}); diff --git a/packages/embark/src/test/plugins.spec.js b/packages/embark/src/test/plugins.spec.js index 053366e15..6cc2ef22d 100644 --- a/packages/embark/src/test/plugins.spec.js +++ b/packages/embark/src/test/plugins.spec.js @@ -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() { diff --git a/packages/embark/src/test/processLauncher.js b/packages/embark/src/test/processLauncher.js index 103e8279c..f54064fd9 100644 --- a/packages/embark/src/test/processLauncher.js +++ b/packages/embark/src/test/processLauncher.js @@ -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({}); diff --git a/packages/embark/src/test/template.js b/packages/embark/src/test/template.js index d5c85fa39..49387299f 100644 --- a/packages/embark/src/test/template.js +++ b/packages/embark/src/test/template.js @@ -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'); diff --git a/packages/embark/src/test/utils.js b/packages/embark/src/test/utils.js index 252ec41b9..93175b730 100644 --- a/packages/embark/src/test/utils.js +++ b/packages/embark/src/test/utils.js @@ -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'); diff --git a/packages/embark/src/test/vm.js b/packages/embark/src/test/vm.js index 4a59813d4..0e0720b2f 100644 --- a/packages/embark/src/test/vm.js +++ b/packages/embark/src/test/vm.js @@ -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'); diff --git a/packages/plugins/accounts-manager/package.json b/packages/plugins/accounts-manager/package.json index a7e030dfb..76bb40268 100644 --- a/packages/plugins/accounts-manager/package.json +++ b/packages/plugins/accounts-manager/package.json @@ -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": { diff --git a/packages/plugins/accounts-manager/src/index.ts b/packages/plugins/accounts-manager/src/index.ts index 2f5218105..05c9f2f22 100644 --- a/packages/plugins/accounts-manager/src/index.ts +++ b/packages/plugins/accounts-manager/src/index.ts @@ -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"); diff --git a/packages/plugins/debugger/src/debugger_manager.ts b/packages/plugins/debugger/src/debugger_manager.ts index d19c231c4..91b4bedd7 100644 --- a/packages/plugins/debugger/src/debugger_manager.ts +++ b/packages/plugins/debugger/src/debugger_manager.ts @@ -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); }); diff --git a/packages/plugins/debugger/src/index.ts b/packages/plugins/debugger/src/index.ts index f948f9419..d6254b278 100644 --- a/packages/plugins/debugger/src/index.ts +++ b/packages/plugins/debugger/src/index.ts @@ -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); }); diff --git a/packages/plugins/deploy-tracker/package.json b/packages/plugins/deploy-tracker/package.json index c8de9279b..3fc3aeb9c 100644 --- a/packages/plugins/deploy-tracker/package.json +++ b/packages/plugins/deploy-tracker/package.json @@ -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" }, diff --git a/packages/plugins/deploy-tracker/src/test/deploymentChecksSpec.js b/packages/plugins/deploy-tracker/src/test/deploymentChecksSpec.js index 5bed6ee3f..9cbf1a8e3 100644 --- a/packages/plugins/deploy-tracker/src/test/deploymentChecksSpec.js +++ b/packages/plugins/deploy-tracker/src/test/deploymentChecksSpec.js @@ -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 () { diff --git a/packages/plugins/deploy-tracker/src/test/trackingFunctionsSpec.js b/packages/plugins/deploy-tracker/src/test/trackingFunctionsSpec.js index 22bdc7d85..b5f02faa3 100644 --- a/packages/plugins/deploy-tracker/src/test/trackingFunctionsSpec.js +++ b/packages/plugins/deploy-tracker/src/test/trackingFunctionsSpec.js @@ -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"); diff --git a/packages/plugins/geth/src/blockchain.js b/packages/plugins/geth/src/blockchain.js index c2939c570..fd57d5a51 100644 --- a/packages/plugins/geth/src/blockchain.js +++ b/packages/plugins/geth/src/blockchain.js @@ -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; diff --git a/packages/plugins/parity/src/blockchain.js b/packages/plugins/parity/src/blockchain.js index cdf69b6a8..c0dbf8627 100644 --- a/packages/plugins/parity/src/blockchain.js +++ b/packages/plugins/parity/src/blockchain.js @@ -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; diff --git a/packages/plugins/scaffolding/package.json b/packages/plugins/scaffolding/package.json index 164e7c026..d11322984 100644 --- a/packages/plugins/scaffolding/package.json +++ b/packages/plugins/scaffolding/package.json @@ -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": { diff --git a/packages/plugins/scaffolding/src/commandOptions.ts b/packages/plugins/scaffolding/src/commandOptions.ts index 23e92bf90..7d6e4e3b9 100644 --- a/packages/plugins/scaffolding/src/commandOptions.ts +++ b/packages/plugins/scaffolding/src/commandOptions.ts @@ -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", diff --git a/packages/plugins/scaffolding/src/smartContractsRecipe.ts b/packages/plugins/scaffolding/src/smartContractsRecipe.ts index 8f624a80b..d6915256d 100644 --- a/packages/plugins/scaffolding/src/smartContractsRecipe.ts +++ b/packages/plugins/scaffolding/src/smartContractsRecipe.ts @@ -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"); diff --git a/packages/stack/blockchain/package.json b/packages/stack/blockchain/package.json index bb4c32b97..1c2f3e095 100644 --- a/packages/stack/blockchain/package.json +++ b/packages/stack/blockchain/package.json @@ -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", diff --git a/packages/stack/blockchain/src/api.ts b/packages/stack/blockchain/src/api.ts index 52bc59fb9..4784b6bcd 100644 --- a/packages/stack/blockchain/src/api.ts +++ b/packages/stack/blockchain/src/api.ts @@ -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; diff --git a/packages/stack/contracts-manager/package.json b/packages/stack/contracts-manager/package.json index e283a59a0..f101c9dd1 100644 --- a/packages/stack/contracts-manager/package.json +++ b/packages/stack/contracts-manager/package.json @@ -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": { diff --git a/packages/stack/contracts-manager/src/contract.ts b/packages/stack/contracts-manager/src/contract.ts index 50daf0db3..ea00ae541 100644 --- a/packages/stack/contracts-manager/src/contract.ts +++ b/packages/stack/contracts-manager/src/contract.ts @@ -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"; diff --git a/packages/stack/proxy/package.json b/packages/stack/proxy/package.json index 39425c453..edf654bce 100644 --- a/packages/stack/proxy/package.json +++ b/packages/stack/proxy/package.json @@ -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", diff --git a/packages/stack/proxy/src/index.ts b/packages/stack/proxy/src/index.ts index a34b0f5f1..0827162de 100644 --- a/packages/stack/proxy/src/index.ts +++ b/packages/stack/proxy/src/index.ts @@ -1,6 +1,7 @@ -import { Embark, Events, Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark"; -import { __ } from "embark-i18n"; +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"); diff --git a/packages/utils/collective/package.json b/packages/utils/collective/package.json index e33269422..5b47ca57f 100644 --- a/packages/utils/collective/package.json +++ b/packages/utils/collective/package.json @@ -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", diff --git a/tsconfig.json b/tsconfig.json index dede4236f..bebff6eb9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,7 @@ "module": "CommonJS", "noEmit": true, "noImplicitThis": false, + "noImplicitAny": false, "strict": true, "target": "ES2017", "resolveJsonModule": true diff --git a/tslint.json b/tslint.json index 29ba5b375..838ae1baa 100644 --- a/tslint.json +++ b/tslint.json @@ -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": [] } diff --git a/yarn.lock b/yarn.lock index b8c7cff5c..0acae0619 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"