Console command connect to ipc

This commit is contained in:
Anthony Laibe 2018-08-08 13:42:45 +01:00 committed by Iuri Matias
parent b1498164a1
commit 27933774a9
15 changed files with 191 additions and 103 deletions

View File

@ -65,6 +65,7 @@ class EmbarkController {
let self = this;
self.context = options.context || [constants.contexts.run, constants.contexts.build];
let Dashboard = require('./dashboard/dashboard.js');
let REPL = require('./dashboard/repl.js');
let webServerConfig = {
enabled: options.runWebserver
@ -101,6 +102,13 @@ class EmbarkController {
async.parallel([
function startDashboard(callback) {
if (!options.useDashboard) {
new REPL({
env: engine.env,
plugins: engine.plugins,
version: engine.version,
events: engine.events,
ipc: engine.ipc
}).startConsole();
return callback();
}
@ -109,7 +117,8 @@ class EmbarkController {
logger: engine.logger,
plugins: engine.plugins,
version: self.version,
env: engine.env
env: engine.env,
ipc: engine.ipc
});
dashboard.start(function () {
engine.logger.info(__('dashboard start'));
@ -243,7 +252,7 @@ class EmbarkController {
console(options) {
this.context = options.context || [constants.contexts.run, constants.contexts.console];
const REPL = require('../lib/dashboard/repl.js');
const REPL = require('./dashboard/repl.js');
const Engine = require('../lib/core/engine.js');
const engine = new Engine({
env: options.env,
@ -253,7 +262,8 @@ class EmbarkController {
embarkConfig: options.embarkConfig || 'embark.json',
logFile: options.logFile,
logLevel: options.logLevel,
context: this.context
context: this.context,
ipcRole: 'client'
});
engine.init();
async.waterfall([
@ -263,25 +273,58 @@ class EmbarkController {
engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", "));
}
engine.startService("processManager");
engine.startService("serviceMonitor");
engine.startService("libraryManager");
engine.startService("codeRunner");
engine.startService("web3");
engine.startService("pipeline");
engine.startService("deployment", {onlyCompile: false});
engine.startService("storage");
engine.startService("codeGenerator");
engine.startService("fileWatcher");
engine.ipc.connect((err) => {
if (err) {
engine.startService("processManager");
engine.startService("serviceMonitor");
engine.startService("libraryManager");
engine.startService("codeRunner");
engine.startService("web3");
engine.startService("pipeline");
engine.startService("deployment");
engine.startService("storage");
engine.startService("codeGenerator");
engine.startService("webServer");
callback();
return callback();
}
engine.startService("codeRunner");
callback();
});
},
function web3IPC(callback) {
if(!engine.ipc.connected || engine.ipc.isServer()) {
return callback();
}
const Web3 = require('web3');
let web3 = new Web3();
engine.ipc.request("runcode:getCommands", null, (_, {web3Config, commands}) => {
web3.setProvider(web3Config.provider.host);
web3.eth.defaultAccount = web3Config.defaultAccount;
engine.events.emit("runcode:register", "web3", web3);
async.each(commands, ({varName, code}, next) => {
if (varName) {
engine.events.emit("runcode:register", varName, code);
} else {
engine.events.request("runcode:eval", code);
}
next();
}, callback);
});
},
function deploy(callback) {
if(engine.ipc.connected && engine.ipc.isClient()) {
return callback();
}
engine.events.request('deploy:contracts', function (err) {
callback(err);
});
},
function waitForWriteFinish(callback) {
if(engine.ipc.connected && engine.ipc.isClient()) {
return callback();
}
engine.logger.info("Finished deploying".underline);
engine.events.once('outputDone', (err) => {
engine.logger.info(__("finished building").underline);
@ -293,7 +336,8 @@ class EmbarkController {
env: engine.env,
plugins: engine.plugins,
version: engine.version,
events: engine.events
events: engine.events,
ipc: engine.ipc
});
repl.start(callback);
}

View File

@ -5,11 +5,11 @@ class Console {
this.events = options.events;
this.plugins = options.plugins;
this.version = options.version;
this.contractsConfig = options.contractsConfig;
}
this.ipc = options.ipc;
runCode(code) {
this.events.request('runcode:eval', code);
if (this.ipc.isServer()) {
this.ipc.on('console:executeCmd', this.executeCmd.bind(this));
}
}
processEmbarkCmd (cmd) {
@ -37,26 +37,25 @@ class Console {
executeCmd(cmd, callback) {
var pluginCmds = this.plugins.getPluginsProperty('console', 'console');
for (let pluginCmd of pluginCmds) {
let pluginOutput = pluginCmd.call(this, cmd, {});
if (pluginOutput !== false && pluginOutput !== 'false' && pluginOutput !== undefined) return callback(pluginOutput);
let pluginResult = pluginCmd.call(this, cmd, {});
if (pluginResult.match()) {
return pluginResult.process(callback);
}
}
let output = this.processEmbarkCmd(cmd);
if (output) {
return callback(output);
return callback(null, output);
}
try {
this.events.request('runcode:eval', cmd, (err, result) => {
callback(result);
});
this.events.request('runcode:eval', cmd, callback, true);
}
catch (e) {
if (e.message.indexOf('not defined') > 0) {
return callback(("error: " + e.message).red + ("\n" + __("Type") + " " + "help".bold + " " + __("to see the list of available commands")).cyan);
} else {
return callback(e.message);
if (this.ipc.connected && this.ipc.isClient()) {
return this.ipc.request('console:executeCmd', cmd, callback);
}
return callback(e.message);
}
}
}

View File

@ -11,6 +11,7 @@ class Dashboard {
this.plugins = options.plugins;
this.version = options.version;
this.env = options.env;
this.ipc = options.ipc;
this.events.on('firstDeploymentDone', this.checkWindowSize.bind(this));
this.events.on('outputDone', this.checkWindowSize.bind(this));
@ -32,7 +33,8 @@ class Dashboard {
console = new Console({
events: self.events,
plugins: self.plugins,
version: self.version
version: self.version,
ipc: self.ipc
});
callback();
},

View File

@ -368,7 +368,7 @@ class Monitor {
executeCmd(cmd, cb) {
const self = this;
self.logText.log('console> '.bold.green + cmd);
self.console.executeCmd(cmd, function (result) {
self.console.executeCmd(cmd, function (_, result) {
self.logText.log(result);
if (cb) {
cb(result);

View File

@ -8,17 +8,21 @@ class REPL {
this.env = options.env;
this.plugins = options.plugins;
this.events = options.events;
this.version = options.version;
this.ipc = options.ipc;
}
startConsole(){
this.console = new Console({
events: this.events,
plugins: this.plugins,
version: options.version
version: this.version,
ipc: this.ipc
});
}
enhancedEval(cmd, context, filename, callback) {
this.console.executeCmd(cmd.trim(), (result) => {
callback(null, result);
});
this.console.executeCmd(cmd.trim(), callback);
}
enhancedWriter(output) {
@ -30,6 +34,7 @@ class REPL {
}
start(done) {
this.startConsole();
this.replServer = repl.start({
prompt: "Embark (" + this.env + ") > ",
useGlobal: true,

View File

@ -17,6 +17,7 @@ class Engine {
this.context = options.context;
this.useDashboard = options.useDashboard;
this.webServerConfig = options.webServerConfig;
this.ipcRole = options.ipcRole;
}
init(_options) {
@ -35,6 +36,11 @@ class Engine {
if (this.interceptLogs || this.interceptLogs === undefined) {
utils.interceptLogs(console, this.logger);
}
this.ipc = new IPC({logger: this.logger, ipcRole: this.ipcRole});
if (this.ipc.isServer()) {
this.ipc.serve();
}
}
registerModule(moduleName, options) {
@ -126,7 +132,8 @@ class Engine {
this.codeRunner = new CodeRunner({
plugins: this.plugins,
events: this.events,
logger: this.logger
logger: this.logger,
ipc: this.ipc
});
}
@ -157,18 +164,13 @@ class Engine {
let self = this;
this.registerModule('compiler', {plugins: self.plugins});
this.ipc = new IPC({logger: this.logger, ipcRole: options.ipcRole});
if (this.ipc.isServer()) {
this.ipc.serve();
}
this.registerModule('solidity', {ipc: this.ipc, useDashboard: this.useDashboard});
this.registerModule('solidity', {ipc: self.ipc, useDashboard: this.useDashboard});
this.registerModule('vyper');
this.registerModule('profiler');
this.registerModule('deploytracker');
this.registerModule('specialconfigs');
this.registerModule('console_listener', {ipc: this.ipc});
this.registerModule('specialconfigs');
this.registerModule('console_listener', {ipc: self.ipc});
this.registerModule('contracts_manager');
this.registerModule('deployment', {plugins: this.plugins, onlyCompile: options.onlyCompile});

View File

@ -52,7 +52,7 @@ class IPC {
return;
}
let reply = function(_err, replyData) {
self.reply(socket, 'compile', replyData);
self.reply(socket, action, replyData);
};
done(data.message, reply, socket);
});
@ -62,6 +62,14 @@ class IPC {
ipc.server.emit(client, 'message', {action: action, message: data});
}
listenTo(action, callback) {
ipc.of['embark'].on(action, callback);
}
broadcast(action, data) {
ipc.server.broadcast(action, data);
}
once(action, cb) {
ipc.of['embark'].once('message', function(msg) {
if (msg.action !== action) {

View File

@ -6,27 +6,50 @@ class CodeRunner {
this.plugins = options.plugins;
this.logger = options.logger;
this.events = options.events;
this.ipc = options.ipc;
this.commands = [];
let self = this;
// necessary to init the context
RunCode.initContext();
if (this.ipc.isServer()) {
this.ipc.on('runcode:getCommands', (_, callback) => {
let result = {web3Config: RunCode.getWeb3Config(), commands: self.commands};
callback(null, result);
});
}
if (this.ipc.isClient() && this.ipc.connected) {
this.ipc.listenTo('runcode:newCommand', function (command) {
if (command.varName) {
self.events.emit("runcode:register", command.varName, command.code);
} else {
self.events.request("runcode:eval", command.code);
}
});
}
this.events.on("runcode:register", (varName, code) => {
if (self.ipc.isServer() && varName !== 'web3') {
self.commands.push({varName, code});
self.ipc.broadcast("runcode:newCommand", {varName, code});
}
RunCode.registerVar(varName, code);
});
this.events.setCommandHandler('runcode:eval', (code, cb) => {
this.events.setCommandHandler('runcode:eval', (code, cb, dashboard = false) => {
if (!cb) {
cb = function() {};
}
try {
let result = RunCode.doEval(code);
cb(null, result);
} catch (e) {
cb(e);
let result = RunCode.doEval(code);
if (!dashboard && self.ipc.isServer()) {
self.commands.push({code});
self.ipc.broadcast("runcode:newCommand", {code});
}
cb(null, result);
});
}
}
module.exports = CodeRunner;

View File

@ -23,8 +23,13 @@ function registerVar(varName, code) {
__mainContext[varName] = code;
}
function getWeb3Config() {
return {defaultAccount:__mainContext.web3.eth.defaultAccount, provider: __mainContext.web3.currentProvider};
}
module.exports = {
doEval: doEval,
registerVar: registerVar,
initContext: initContext
doEval,
registerVar,
initContext,
getWeb3Config
};

View File

@ -1,13 +1,3 @@
let async = require('async');
const constants = require('./constants');
require('colors');
// Set PWD to CWD since Windows doesn't have a value for PWD
if (!process.env.PWD) {
process.env.PWD = process.cwd();
}
let version = require('../package.json').version;
class Embark {
@ -29,7 +19,6 @@ class Embark {
this.config.loadConfigFiles(options);
this.plugins = this.config.plugins;
}
}
module.exports = Embark;

View File

@ -38,14 +38,16 @@ class LibraryManager {
registerCommands() {
const self = this;
this.embark.registerConsoleCommand((cmd, _options) => {
if (cmd === "versions" || cmd === __('versions')) {
let text = [__('versions in use') + ':'];
for (let lib in self.versions) {
text.push(lib + ": " + self.versions[lib]);
return {
match: () => cmd === "versions" || cmd === __('versions'),
process: (callback) => {
let text = [__('versions in use') + ':'];
for (let lib in self.versions) {
text.push(lib + ": " + self.versions[lib]);
}
callback(null, text.join('\n'));
}
return text.join('\n');
}
return false;
};
});
}

View File

@ -11,7 +11,7 @@ class Profiler {
this.registerConsoleCommand();
}
profile(contractName, contract) {
profile(contractName, contract, callback) {
const self = this;
let table = new asciiTable(contractName);
table.setHeading('Function', 'Payable', 'Mutability', 'Inputs', 'Outputs', 'Gas Estimates');
@ -33,7 +33,7 @@ class Profiler {
table.addRow(abiMethod.name, abiMethod.payable, abiMethod.stateMutability, self.formatParams(abiMethod.inputs), self.formatParams(abiMethod.outputs), gastimates[abiMethod.name]);
}
});
self.logger.info(table.toString());
callback(null, table.toString());
});
}
@ -53,18 +53,18 @@ class Profiler {
self.embark.registerConsoleCommand((cmd, _options) => {
let cmdName = cmd.split(' ')[0];
let contractName = cmd.split(' ')[1];
if (cmdName === 'profile') {
self.events.request('contracts:contract', contractName, (contract) => {
if (!contract || !contract.deployedAddress) {
self.logger.info("-- couldn't profile " + contractName + " - it's not deployed or could be an interface");
return "";
}
self.logger.info("-- profile for " + contractName);
this.profile(contractName, contract);
});
return "";
}
return false;
return {
match: () => cmdName === 'profile',
process: (callback) => {
self.events.request('contracts:contract', contractName, (contract) => {
if (!contract || !contract.deployedAddress) {
return "-- couldn't profile " + contractName + " - it's not deployed or could be an interface";
}
this.profile(contractName, contract, callback);
});
}
};
});
}
}

View File

@ -50,18 +50,25 @@ class WebServer {
registerConsoleCommands() {
const self = this;
self.embark.registerConsoleCommand((cmd, _options) => {
if (cmd === 'webserver start') {
self.events.request("start-webserver");
return " ";
}
if (cmd === 'webserver stop') {
self.events.request("stop-webserver");
return __("stopping webserver") + "...";
}
return false;
return {
match: () => cmd === "webserver start",
process: (callback) => {
self.events.request("start-webserver");
callback(null, "OK");
}
};
});
self.embark.registerConsoleCommand((cmd, _options) => {
return {
match: () => cmd === "webserver stop",
process: (callback) => {
self.events.request("stop-webserver");
callback(null, "OK");
}
};
});
}
}
module.exports = WebServer;

View File

@ -116,8 +116,7 @@ class Test {
web3: this.web3
});
this.engine.startService("deployment", {
trackContracts: false,
ipcRole: 'client'
trackContracts: false
});
this.events.request('deploy:setGasLimit', 6000000);
this.engine.startService("codeCoverage");
@ -128,7 +127,8 @@ class Test {
env: this.options.env || 'test',
// TODO: config will need to detect if this is a obj
embarkConfig: this.options.embarkConfig || 'embark.json',
interceptLogs: false
interceptLogs: false,
ipcRole: 'client'
});
this.engine.init({

View File

@ -1,19 +1,21 @@
/*globals describe, it*/
let Console = require('../cmd/dashboard/console.js');
let Plugins = require('../lib/core/plugins.js');
let IPC = require('../lib/core/ipc.js');
let assert = require('assert');
let version = require('../package.json').version;
describe('embark.Console', function() {
let ipc = new IPC({ipcRole: 'none'});
let plugins = new Plugins({plugins: {}});
let console = new Console({plugins: plugins, version: version});
let console = new Console({plugins, version, ipc});
describe('#executeCmd', function() {
describe('command: help', function() {
it('it should provide a help text', function(done) {
console.executeCmd('help', function(output) {
console.executeCmd('help', function(_err, output) {
let lines = output.split('\n');
assert.equal(lines[0], 'Welcome to Embark ' + version);
assert.equal(lines[2], 'possible commands are:');