diff --git a/lib/cmds/blockchain/blockchain.js b/lib/cmds/blockchain/blockchain.js index 116e662b..e83167bc 100644 --- a/lib/cmds/blockchain/blockchain.js +++ b/lib/cmds/blockchain/blockchain.js @@ -1,94 +1,94 @@ -let colors = require('colors'); -let shelljs = require('shelljs'); +var colors = require('colors'); +var shelljs = require('shelljs'); -let fs = require('../../core/fs.js'); +var fs = require('../../core/fs.js'); -let GethCommands = require('./geth_commands.js'); +var GethCommands = require('./geth_commands.js'); -let BlockchainClient = function(blockchainConfig, client, env) { +/*eslint complexity: ["error", 22]*/ +var Blockchain = function(options) { + this.blockchainConfig = options.blockchainConfig; + this.env = options.env || 'development'; + this.client = options.client; + + this.config = { + geth_bin: this.blockchainConfig.geth_bin || 'geth', + networkType: this.blockchainConfig.networkType || 'custom', + genesisBlock: this.blockchainConfig.genesisBlock || false, + datadir: this.blockchainConfig.datadir || false, + mineWhenNeeded: this.blockchainConfig.mineWhenNeeded || false, + rpcHost: this.blockchainConfig.rpcHost || 'localhost', + rpcPort: this.blockchainConfig.rpcPort || 8545, + rpcCorsDomain: this.blockchainConfig.rpcCorsDomain || false, + networkId: this.blockchainConfig.networkId || 12301, + port: this.blockchainConfig.port || 30303, + nodiscover: this.blockchainConfig.nodiscover || false, + mine: this.blockchainConfig.mine || false, + account: this.blockchainConfig.account || {}, + whisper: (this.blockchainConfig.whisper === undefined) || this.blockchainConfig.whisper, + maxpeers: ((this.blockchainConfig.maxpeers === 0) ? 0 : (this.blockchainConfig.maxpeers || 25)), + bootnodes: this.blockchainConfig.bootnodes || "", + rpcApi: (this.blockchainConfig.rpcApi || ['eth', 'web3', 'net']), + vmdebug: this.blockchainConfig.vmdebug || false + }; + + this.client = new options.client({config: this.config, env: this.env}); +}; + +Blockchain.prototype.runCommand = function(cmd) { + console.log(("running: " + cmd.underline).green); + return shelljs.exec(cmd); +}; + +Blockchain.prototype.run = function() { + var self = this; + console.log("===============================================================================".magenta); + console.log("===============================================================================".magenta); + console.log(("Embark Blockchain Using: " + this.client.name.underline).magenta); + console.log("===============================================================================".magenta); + console.log("===============================================================================".magenta); + var address = this.initChainAndGetAddress(); + this.client.mainCommand(address, function(cmd) { + self.runCommand(cmd); + }); +}; + +Blockchain.prototype.initChainAndGetAddress = function() { + var address = null, result; + + // ensure datadir exists, bypassing the interactive liabilities prompt. + this.datadir = '.embark/' + this.env + '/datadir'; + fs.mkdirpSync(this.datadir); + + // copy mining script + fs.copySync(fs.embarkPath("js"), ".embark/" + this.env + "/js", {overwrite: true}); + + // check if an account already exists, create one if not, return address + result = this.runCommand(this.client.listAccountsCommand()); + if (result.output === undefined || result.output === '' || result.output.indexOf("Fatal") >= 0) { + console.log("no accounts found".green); + if (this.config.genesisBlock) { + console.log("initializing genesis block".green); + result = this.runCommand(this.client.initGenesisCommmand()); + } + + result = this.runCommand(this.client.newAccountCommand()); + address = result.output.match(/{(\w+)}/)[1]; + } else { + console.log("already initialized".green); + address = result.output.match(/{(\w+)}/)[1]; + } + + return address; +}; + +var BlockchainClient = function(blockchainConfig, client, env) { if (client === 'geth') { - return new Blockchain({blockchainConfig: blockchainConfig, client: new GethCommands(), env: env}); + return new Blockchain({blockchainConfig: blockchainConfig, client: GethCommands, env: env}); } else { throw new Error('unknown client'); } }; -/*eslint complexity: ["error", 22]*/ -class Blockchain { - constructor(options) { - this.blockchainConfig = options.blockchainConfig; - this.env = options.env || 'development'; - this.client = options.client; - - this.config = { - geth_bin: this.blockchainConfig.geth_bin || 'geth', - networkType: this.blockchainConfig.networkType || 'custom', - genesisBlock: this.blockchainConfig.genesisBlock || false, - datadir: this.blockchainConfig.datadir || false, - mineWhenNeeded: this.blockchainConfig.mineWhenNeeded || false, - rpcHost: this.blockchainConfig.rpcHost || 'localhost', - rpcPort: this.blockchainConfig.rpcPort || 8545, - rpcCorsDomain: this.blockchainConfig.rpcCorsDomain || false, - networkId: this.blockchainConfig.networkId || 12301, - port: this.blockchainConfig.port || 30303, - nodiscover: this.blockchainConfig.nodiscover || false, - mine: this.blockchainConfig.mine || false, - account: this.blockchainConfig.account || {}, - whisper: (this.blockchainConfig.whisper === undefined) || this.blockchainConfig.whisper, - maxpeers: ((this.blockchainConfig.maxpeers === 0) ? 0 : (this.blockchainConfig.maxpeers || 25)), - bootnodes: this.blockchainConfig.bootnodes || "", - rpcApi: (this.blockchainConfig.rpcApi || ['eth', 'web3', 'net']), - vmdebug: this.blockchainConfig.vmdebug || false - }; - } - - runCommand(cmd) { - console.log(("running: " + cmd.underline).green); - return shelljs.exec(cmd); - } - - run () { - let self = this; - console.log("===============================================================================".magenta); - console.log("===============================================================================".magenta); - console.log(("Embark Blockchain Using: " + this.client.name.underline).magenta); - console.log("===============================================================================".magenta); - console.log("===============================================================================".magenta); - let address = this.initChainAndGetAddress(); - this.client.mainCommand(address, function(cmd) { - shelljs.exec(cmd, {async : true}); - }); - } - - initChainAndGetAddress() { - let address = null, result; - - // ensure datadir exists, bypassing the interactive liabilities prompt. - this.datadir = '.embark/' + this.env + '/datadir'; - fs.mkdirpSync(this.datadir); - - // copy mining script - fs.copySync(fs.embarkPath("js"), ".embark/" + this.env + "/js", {overwrite: true}); - - // check if an account already exists, create one if not, return address - result = this.runCommand(this.client.listAccountsCommand()); - if (result.output === undefined || result.output === '' || result.output.indexOf("Fatal") >= 0) { - console.log("no accounts found".green); - if (this.config.genesisBlock) { - console.log("initializing genesis block".green); - result = this.runCommand(this.client.initGenesisCommmand()); - } - - result = this.runCommand(this.client.newAccountCommand()); - address = result.output.match(/{(\w+)}/)[1]; - } else { - console.log("already initialized".green); - address = result.output.match(/{(\w+)}/)[1]; - } - - return address; - } -} - module.exports = BlockchainClient; diff --git a/lib/contracts/deploy_manager.js b/lib/contracts/deploy_manager.js index 86e41ca2..3b3ec750 100644 --- a/lib/contracts/deploy_manager.js +++ b/lib/contracts/deploy_manager.js @@ -1,17 +1,16 @@ let async = require('async'); let Deploy = require('./deploy.js'); let ContractsManager = require('./contracts.js'); -let EventEmitter = require('events'); class DeployManager { constructor(options) { this.config = options.config; this.logger = options.logger; this.blockchainConfig = this.config.blockchainConfig; + this.events = options.events; this.plugins = options.plugins; this.web3 = options.web3; this.chainConfig = (options.trackContracts !== false) ? this.config.chainTracker : false; - Object.create(EventEmitter.prototype); } deployContracts(done) { @@ -19,7 +18,7 @@ class DeployManager { if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) { self.logger.info("Blockchain component is disabled in the config".underline); - this.emit('blockchainDisabled', {}); + this.events.emit('blockchainDisabled', {}); return done(); } @@ -73,7 +72,7 @@ class DeployManager { env: self.config.env }); deploy.deployAll(function () { - self.emit('contractsDeployed', contractsManager); + self.events.emit('contractsDeployed', contractsManager); callback(null, contractsManager); }); } diff --git a/lib/core/config.js b/lib/core/config.js index 9cae005f..65198636 100644 --- a/lib/core/config.js +++ b/lib/core/config.js @@ -76,7 +76,7 @@ Config.prototype.loadContractsConfigFile = function () { let configObject = {}; let configPlugins = []; - this.plugins.emit('get', 'contractsConfig', (kinds) => { + this.events.emit('get', 'contractsConfig', (kinds) => { configPlugins = kinds; }); if (configPlugins.length > 0) { diff --git a/lib/core/engine.js b/lib/core/engine.js index 0449ff81..6d7af0fb 100644 --- a/lib/core/engine.js +++ b/lib/core/engine.js @@ -10,14 +10,13 @@ let ServicesMonitor = require('./services_monitor.js'); let Pipeline = require('../pipeline/pipeline.js'); let Server = require('../pipeline/server.js'); let Watch = require('../pipeline/watch.js'); -let version = require('../../package.json'); class Engine { constructor(options) { this.env = options.env; this.embarkConfig = options.embarkConfig; this.interceptLogs = options.interceptLogs; - this.version = version; + this.version = options.version; } init(_options) { diff --git a/lib/core/events.js b/lib/core/events.js index ebb3992e..69e0177b 100644 --- a/lib/core/events.js +++ b/lib/core/events.js @@ -1,12 +1,3 @@ -//TODO: This is deprecated because Embark extends EventEmitter now -let events = require('events'); - -class EventEmitter { - constructor(options) { - this.options = options; - } -} - -EventEmitter.prototype = Object.create(events.EventEmitter.prototype); +var EventEmitter = require('events'); module.exports = EventEmitter; diff --git a/lib/core/plugin.js b/lib/core/plugin.js index adef6da9..45a498f0 100644 --- a/lib/core/plugin.js +++ b/lib/core/plugin.js @@ -1,59 +1,46 @@ /*jshint esversion: 6, loopfunc: true */ -let fs = require('./fs.js'); -let utils = require('../utils/utils.js'); -let camelcase = require("underscore.string").camelcase; +var fs = require('./fs.js'); +var utils = require('../utils/utils.js'); -class Plugin { - constructor(options) { - this.config = {}; - for (let opt in options) { - if (options.hasOwnProperty(opt)) { - this.config[opt] = options[opt]; - } - } - let requiredOptions = ['name', 'pluginModule', 'pluginPath', 'config', 'interceptLogs', 'logger']; +// TODO: pass other params like blockchainConfig, contract files, etc.. +var Plugin = function(options) { + this.name = options.name; + this.pluginModule = options.pluginModule; + this.pluginPath = options.pluginPath; + this.pluginConfig = options.pluginConfig; + this.shouldInterceptLogs = options.interceptLogs; + this.clientWeb3Providers = []; + this.contractsGenerators = []; + this.pipeline = []; + this.pipelineFiles = []; + this.console = []; + this.contractsConfigs = []; + this.contractsFiles = []; + this.compilers = []; + this.serviceChecks = []; + this.pluginTypes = []; + this.logger = options.logger; + this.events = options.events; + this.config = options.config; +}; - for (let i = 0; requiredOptions.length > i; i++) { - if (!(utils.contains(Object.keys(this.config), requiredOptions[i]))) { - throw new Error('Missing required plugin configuration key: ' + requiredOptions[i]); - } - } - - this.clientWeb3Providers = []; - this.contractsGenerators = []; - this.pipeline = []; - this.pipelineFiles = []; - this.console = []; - this.contractsConfigs = []; - this.contractsFiles = []; - this.compilers = []; - this.serviceChecks = []; - this.pluginTypes = []; - - if (!(this instanceof Plugin)) { - return new Plugin(); - } - } -} - -Plugin.prototype.runPlugin = Plugin.prototype.run = function () { +Plugin.prototype.loadPlugin = function() { if (this.shouldInterceptLogs) { this.interceptLogs(this.pluginModule); } - let fullyQualifiedPath = this.pathToFile(this.config.pluginModule); - this.call(this.loadPluginFile(fullyQualifiedPath), this); + (this.pluginModule.call(this, this)); }; -Plugin.prototype.loadPluginFile = function (filename) { +Plugin.prototype.loadPluginFile = function(filename) { return fs.readFileSync(this.pathToFile(filename)).toString(); }; -Plugin.prototype.pathToFile = function (filename) { +Plugin.prototype.pathToFile = function(filename) { return utils.joinPath(this.pluginPath, filename); }; -Plugin.prototype.interceptLogs = function (context) { - let self = this; +Plugin.prototype.interceptLogs = function(context) { + var self = this; // TODO: this is a bit nasty, figure out a better way context.console = context.console || console; @@ -62,125 +49,112 @@ Plugin.prototype.interceptLogs = function (context) { // //self.logger.error.apply(self.logger, arguments); // self.logger.error(self.name + " > " + txt); //}; - context.console.log = function (txt) { + context.console.log = function(txt) { self.logger.info(self.name + " > " + txt); }; - context.console.warn = function (txt) { + context.console.warn = function(txt) { self.logger.warn(self.name + " > " + txt); }; - context.console.info = function (txt) { + context.console.info = function(txt) { self.logger.info(self.name + " > " + txt); }; - context.console.debug = function (txt) { + context.console.debug = function(txt) { // TODO: ue JSON.stringify self.logger.debug(self.name + " > " + txt); }; - context.console.trace = function (txt) { + context.console.trace = function(txt) { self.logger.trace(self.name + " > " + txt); }; }; -Plugin.prototype.register = function (classname, cb) { - let camelCasedClassname = camelcase(classname); - this[camelCasedClassname].push(cb); - this.pluginTypes.push({class: classname, call: cb}); -}; - -["ClientWeb3Provider", "ContractsGeneration", "Pipeline", "Deployer", - "ConsoleCommand", "ServiceCheck", "ContractConfiguration", "Compiler"].forEach(function (name) { - Plugin.prototype["register" + name] = function (cb) { - Plugin.prototype.register.call(name, cb); - }; -}); - // TODO: add deploy provider -Plugin.prototype.registerClientWeb3Provider = function (cb) { +Plugin.prototype.registerClientWeb3Provider = function(cb) { this.clientWeb3Providers.push(cb); this.pluginTypes.push('clientWeb3Provider'); }; -Plugin.prototype.registerContractsGeneration = function (cb) { +Plugin.prototype.registerContractsGeneration = function(cb) { this.contractsGenerators.push(cb); this.pluginTypes.push('contractGeneration'); }; -Plugin.prototype.registerPipeline = function (matcthingFiles, cb) { +Plugin.prototype.registerPipeline = function(matcthingFiles, cb) { // TODO: generate error for more than one pipeline per plugin this.pipeline.push({matcthingFiles: matcthingFiles, cb: cb}); this.pluginTypes.push('pipeline'); }; -Plugin.prototype.addFileToPipeline = function (file, intendedPath, options) { +Plugin.prototype.addFileToPipeline = function(file, intendedPath, options) { this.pipelineFiles.push({file: file, intendedPath: intendedPath, options: options}); this.pluginTypes.push('pipelineFiles'); }; -Plugin.prototype.addContractFile = function (file) { +Plugin.prototype.addContractFile = function(file) { this.contractsFiles.push(file); this.pluginTypes.push('contractFiles'); }; -Plugin.prototype.registerConsoleCommand = function (cb) { +Plugin.prototype.registerConsoleCommand = function(cb) { this.console.push(cb); this.pluginTypes.push('console'); }; -Plugin.prototype.registerServiceCheck = function (checkName, checkFn, time) { +Plugin.prototype.registerServiceCheck = function(checkName, checkFn, time) { this.serviceChecks.push({checkName: checkName, checkFn: checkFn, time: time}); this.pluginTypes.push('serviceChecks'); }; -Plugin.prototype.has = function (pluginType) { +Plugin.prototype.has = function(pluginType) { return this.pluginTypes.indexOf(pluginType) >= 0; }; -Plugin.prototype.generateProvider = function (args) { - return this.clientWeb3Providers.map(function (cb) { +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) { +Plugin.prototype.generateContracts = function(args) { + return this.contractsGenerators.map(function(cb) { return cb.call(this, args); }).join("\n"); }; -Plugin.prototype.registerContractConfiguration = function (config) { +Plugin.prototype.registerContractConfiguration = function(config) { this.contractsConfigs.push(config); this.pluginTypes.push('contractsConfig'); }; -Plugin.prototype.registerCompiler = function (extension, cb) { +Plugin.prototype.registerCompiler = function(extension, cb) { this.compilers.push({extension: extension, cb: cb}); this.pluginTypes.push('compilers'); }; -Plugin.prototype.runCommands = function (cmd, options) { - return this.console.map(function (cb) { +Plugin.prototype.runCommands = function(cmd, options) { + return this.console.map(function(cb) { return cb.call(this, cmd, options); }).join("\n"); }; -Plugin.prototype.runFilePipeline = function () { - let self = this; +Plugin.prototype.runFilePipeline = function() { + var self = this; - return this.pipelineFiles.map(function (file) { - let 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 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; + return obj; }); }; -Plugin.prototype.runPipeline = function (args) { +Plugin.prototype.runPipeline = function(args) { // TODO: should iterate the pipelines - let pipeline = this.pipeline[0]; - let shouldRunPipeline = utils.fileMatchesPattern(pipeline.matcthingFiles, args.targetFile); + var pipeline = this.pipeline[0]; + var shouldRunPipeline = utils.fileMatchesPattern(pipeline.matcthingFiles, args.targetFile); if (shouldRunPipeline) { return pipeline.cb.call(this, args); } else { diff --git a/lib/core/plugins.js b/lib/core/plugins.js index 40057db4..c3319183 100644 --- a/lib/core/plugins.js +++ b/lib/core/plugins.js @@ -1,60 +1,45 @@ -const _ = require('underscore'); -const EventEmitter = require('events').EventEmitter; +var Plugin = require('./plugin.js'); +var utils = require('../utils/utils.js'); -const getPluginsFor = function (pluginType, plugins) { - return _.filter(plugins, pluginType); +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; }; -class Plugins extends EventEmitter { - constructor(options) { - super(); - //TODO: put an observer on this.plugins and call loadPlugin when a new item is added - this.config = {}; - - for (let opt in options) { - if (options.hasOwnProperty(opt)) { - this.config[opt] = options[opt]; - } - } - - let requiredOptions = ['interceptLogs', 'plugins', 'logger']; - for (let i = 0; requiredOptions.length > i; i++) { - if (!(_.contains(Object.keys(this.config), requiredOptions[i]))) { - console.log('Warning: missing required plugin configuration key: ' + requiredOptions[i]); - } - } - this.on('load', () => { - this.load(); - }); - - this.on('get', (pluginType, cb) => { - let pluginTypes = getPluginsFor(pluginType, this.config.plugins); - return cb(pluginTypes); - }); +Plugins.prototype.loadPlugins = function() { + var pluginConfig; + for (var pluginName in this.pluginList) { + pluginConfig = this.pluginList[pluginName]; + this.loadPlugin(pluginName, pluginConfig); } +}; - load() { - let pluginConfig; - for (let i = 0; this.config.plugins.length > i; i++) { - pluginConfig = this.config.plugins[i].config; - let Plugin = require('./plugin'); - let plugin = new Plugin(pluginConfig); - plugin.run(); - } +Plugins.prototype.listPlugins = function() { + var list = []; + for (var className in this.pluginList) { + list.push(className); } + return list; +}; - loadPlugins () { - return this.load(); - } +Plugins.prototype.loadPlugin = function(pluginName, pluginConfig) { + var pluginPath = utils.joinPath(process.env.PWD, 'node_modules', pluginName); + var plugin = require(pluginPath); - listPlugins() { - return this.config.plugins.join(', '); - } + var pluginWrapper = new Plugin({name: pluginName, pluginModule: plugin, pluginConfig: pluginConfig, logger: this.logger, pluginPath: pluginPath, interceptLogs: this.interceptLogs, events: this.events, config: this.config}); + pluginWrapper.loadPlugin(); + this.plugins.push(pluginWrapper); +}; - getPluginsFor(pluginType, plugins) { - return getPluginsFor(pluginType, plugins); - } +Plugins.prototype.getPluginsFor = function(pluginType) { + return this.plugins.filter(function(plugin) { + return plugin.has(pluginType); + }); +}; -} - -module.exports = Plugins; \ No newline at end of file +module.exports = Plugins; diff --git a/lib/dashboard/console.js b/lib/dashboard/console.js index d4453dac..ca8ccd82 100644 --- a/lib/dashboard/console.js +++ b/lib/dashboard/console.js @@ -32,12 +32,9 @@ class Console { } executeCmd(cmd, callback) { - let plugin, pluginOutput; - let plugins = []; - this.plugins.emit('get', 'console', (list) => { - plugins = list; - }); - for (let i = 0; i < plugins.length; i++) { + var plugin, pluginOutput; + var plugins = this.plugins.getPluginsFor('console'); + for (var i = 0; i < plugins.length; i++) { plugin = plugins[i]; pluginOutput = plugin.runCommands(cmd, {}); if (pluginOutput !== false && pluginOutput !== 'false') return callback(pluginOutput); diff --git a/lib/index.js b/lib/index.js index 00e94968..0715b2dc 100644 --- a/lib/index.js +++ b/lib/index.js @@ -11,12 +11,11 @@ let Swarm = require('./upload/swarm.js'); let version = require('../package.json').version; -const EventEmitter = require('events').EventEmitter; +let Events = require('events'); -class Embark extends EventEmitter { +class Embark { constructor (options) { - super(); this.version = version; this.options = options || {}; } @@ -51,19 +50,21 @@ class Embark extends EventEmitter { } run(options) { + let self = this; let Dashboard = require('./dashboard/dashboard.js'); let env = options.env; let engine = new Engine({ env: options.env, + version: this.version, embarkConfig: options.embarkConfig || 'embark.json' }); engine.init(); if (!options.useDashboard) { console.log('========================'.bold.green); - console.log(('Welcome to Embark ' + Embark.version).yellow.bold); + console.log(('Welcome to Embark ' + this.version).yellow.bold); console.log('========================'.bold.green); } @@ -76,7 +77,7 @@ class Embark extends EventEmitter { let dashboard = new Dashboard({ logger: engine.logger, plugins: engine.plugins, - version: engine.version, + version: self.version, env: engine.env }); dashboard.start(function () { @@ -141,6 +142,7 @@ class Embark extends EventEmitter { let engine = new Engine({ env: options.env, + version: this.version, embarkConfig: 'embark.json', interceptLogs: false });