embark-area-51/lib/core/engine.js

245 lines
7.9 KiB
JavaScript

var http = require('http');
var Web3 = require('web3');
var utils = require('../utils/utils.js');
var Events = require('./events.js');
var Logger = require('./logger.js');
var Config = require('./config.js');
var DeployManager = require('../contracts/deploy_manager.js');
var ABIGenerator = require('../contracts/abi.js');
var ServicesMonitor = require('./services_monitor.js');
var Pipeline = require('../pipeline/pipeline.js');
var Server = require('../pipeline/server.js');
var Watch = require('../pipeline/watch.js');
var version = require('../../package.json').version;
var Engine = function(options) {
this.env = options.env;
this.embarkConfig = options.embarkConfig;
this.interceptLogs = options.interceptLogs;
this.version = version;
};
Engine.prototype.init = function(_options) {
var self = this;
var options = _options || {};
this.events = new Events();
this.logger = options.logger || new Logger({logLevel: 'debug'});
this.config = new Config({env: this.env, logger: this.logger, events: this.events});
this.config.loadConfigFiles({embarkConfig: this.embarkConfig, interceptLogs: this.interceptLogs});
this.plugins = this.config.plugins;
this.servicesMonitor = new ServicesMonitor({events: this.events, logger: this.logger});
this.servicesMonitor.addCheck('embarkVersion', function(cb) {
return cb({name: 'Embark ' + self.version, status: 'green'});
}, 0);
};
Engine.prototype.startMonitor = function() {
var self = this;
if (this.plugins) {
var servicePlugins = this.plugins.getPluginsFor('serviceChecks');
servicePlugins.forEach(function(plugin) {
plugin.serviceChecks.forEach(function(pluginCheck) {
self.servicesMonitor.addCheck(pluginCheck.checkName, pluginCheck.checkFn, pluginCheck.time);
});
});
}
this.servicesMonitor.startMonitor();
};
Engine.prototype.startService = function(serviceName, _options) {
var options = _options || {};
var services = {
"pipeline": this.pipelineService,
"abi": this.abiService,
"deployment": this.deploymentService,
"fileWatcher": this.fileWatchService,
"webServer": this.webServerService,
"ipfs": this.ipfsService,
"web3": this.web3Service
};
var service = services[serviceName];
if (!service) {
throw new Error("unknown service: " + serviceName);
}
// need to be careful with circular references due to passing the web3 object
//this.logger.trace("calling: " + serviceName + "(" + JSON.stringify(options) + ")");
return service.apply(this, [options]);
};
Engine.prototype.pipelineService = function(options) {
var self = this;
this.logger.setStatus("Building Assets");
var pipeline = new Pipeline({
buildDir: this.config.buildDir,
contractsFiles: this.config.contractsFiles,
assetFiles: this.config.assetFiles,
logger: this.logger,
plugins: this.plugins
});
this.events.on('abi', function(abi) {
self.currentAbi = abi;
pipeline.build(abi);
self.events.emit('outputDone');
});
// TODO: still need to redeploy contracts because the original contracts
// config is being corrupted
//this.events.on('file-event', function(fileType, path) {
// if (fileType === 'asset') {
// self.config.reloadConfig();
// pipeline.build(self.abi, path);
// self.events.emit('outputDone');
// }
//});
};
Engine.prototype.abiService = function(options) {
var self = this;
var generateABICode = function(contractsManager) {
var abiGenerator = new ABIGenerator({
blockchainConfig: self.config.blockchainConfig,
contractsManager: contractsManager,
plugins: self.plugins,
storageConfig: self.config.storageConfig,
communicationConfig: self.config.communicationConfig
});
var embarkJSABI = abiGenerator.generateABI({useEmbarkJS: true});
var vanillaABI = abiGenerator.generateABI({useEmbarkJS: false});
var vanillaContractsABI = abiGenerator.generateContracts(false);
self.events.emit('abi-contracts-vanila', vanillaContractsABI);
self.events.emit('abi-vanila', vanillaABI);
self.events.emit('abi', embarkJSABI);
};
this.events.on('contractsDeployed', generateABICode);
this.events.on('blockchainDisabled', generateABICode);
};
Engine.prototype.deploymentService = function(options) {
var self = this;
this.deployManager = new DeployManager({
web3: options.web3 || self.web3,
trackContracts: options.trackContracts,
config: this.config,
logger: this.logger,
plugins: this.plugins,
events: this.events
});
this.events.on('file-event', function(fileType, path) {
// TODO: for now need to deploy on asset chanes as well
// because the contractsManager config is corrupted after a deploy
//if (fileType === 'contract' || fileType === 'config') {
self.config.reloadConfig();
self.deployManager.deployContracts(function() {});
//}
});
};
Engine.prototype.fileWatchService = function(options) {
this.logger.setStatus("Watching for changes");
var watch = new Watch({logger: this.logger, events: this.events});
watch.start();
};
Engine.prototype.webServerService = function(options) {
var self = this;
var webServerConfig = this.config.webServerConfig;
if (!webServerConfig.enabled) { return; }
var host = options.host || webServerConfig.host;
var port = options.port || webServerConfig.port;
this.logger.setStatus("Starting Server");
var server = new Server({
logger: this.logger,
host: host,
port: port
});
self.servicesMonitor.addCheck('Webserver', function(cb) {
var devServer = 'Webserver (http://' + host + ':' + port + ')';
return cb({name: devServer, status: 'green'});
});
server.start(function(){
});
};
Engine.prototype.ipfsService = function(options) {
var self = this;
self.servicesMonitor.addCheck('IPFS', function(cb) {
utils.checkIsAvailable('http://localhost:5001', function(available) {
if (available) {
//Ideally this method should be in an IPFS API JSONRPC wrapper
//The URL should also be flexible to accept non-default IPFS url
self.logger.trace("Checking IPFS version...");
http.get('http://localhost:5001/api/v0/version', function(res) {
var body = '';
res.on('data', function(d) {
body += d;
});
res.on('end', function() {
try{
var parsed = JSON.parse(body);
if(parsed.Version){
return cb({name: ("IPFS " + parsed.Version), status: 'green'});
}
else{
return cb({name: "IPFS ", status: 'green'});
}
}
catch (e){
return cb({name: "IPFS ", status: 'red'});
}
});
res.on('error', function(err) {
self.logger.trace("Check IPFS version error: " + err);
return cb({name: "IPFS ", status: 'red'});
});
});
}
else {
return cb({name: "IPFS ", status: 'red'});
}
});
});
};
Engine.prototype.web3Service = function(options) {
var self = this;
this.web3 = options.web3;
if (this.web3 === undefined) {
this.web3 = new Web3();
var web3Endpoint = 'http://' + this.config.blockchainConfig.rpcHost + ':' + this.config.blockchainConfig.rpcPort;
this.web3.setProvider(new this.web3.providers.HttpProvider(web3Endpoint));
}
self.servicesMonitor.addCheck('Ethereum', function(cb) {
if (self.web3.isConnected()) {
return cb({name: (self.web3.version.node.split("/")[0] + " " + self.web3.version.node.split("/")[1].split("-")[0] + " (Ethereum)"), status: 'green'});
} else {
return cb({name: "No Blockchain node found", status: 'red'});
}
});
self.servicesMonitor.addCheck('Whisper', function(cb) {
self.web3.version.getWhisper(function(err, res) {
if (err) {
return cb({name: 'Whisper', status: 'red'});
} else {
return cb({name: 'Whisper', status: 'green'});
}
});
});
};
module.exports = Engine;