From e432dc328cc36cd5a3d2f42b478f367009d295bc Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Tue, 30 Jul 2019 15:00:45 -0400 Subject: [PATCH] implement communication stack component, whisper plugin --- packages/embark-ipfs/__src/index.js | 312 ------------------ packages/embark-ipfs/src/index.js | 3 - packages/embark-storage/src/index.js | 66 ---- packages/embark-whisper/src/index.js | 229 ++++--------- packages/embark/src/cmd/cmd_controller.js | 7 + packages/embark/src/lib/core/engine.js | 6 + .../src/lib/modules/communication/index.js | 48 +++ 7 files changed, 120 insertions(+), 551 deletions(-) delete mode 100644 packages/embark-ipfs/__src/index.js create mode 100644 packages/embark/src/lib/modules/communication/index.js diff --git a/packages/embark-ipfs/__src/index.js b/packages/embark-ipfs/__src/index.js deleted file mode 100644 index e9725c1d7..000000000 --- a/packages/embark-ipfs/__src/index.js +++ /dev/null @@ -1,312 +0,0 @@ -import { __ } from 'embark-i18n'; -const UploadIPFS = require('./upload.js'); -const IpfsApi = require('ipfs-api'); -const StorageProcessesLauncher = require('embark-storage/processes'); -const constants = require('embark-core/constants'); -import { buildUrlFromConfig, dappPath, embarkPath, getJson } from 'embark-utils'; -import * as path from 'path'; - -class IPFS { - - constructor(embark, options) { - this.logger = embark.logger; - this.events = embark.events; - this.buildDir = options.buildDir; - this.embarkConfig = embark.config.embarkConfig; - this.config = embark.config; - this.namesystemConfig = embark.config.namesystemConfig; - this.embark = embark; - this.fs = embark.fs; - this.addedToConsole = false; - this.storageProcessesLauncher = null; - this.usingRunningNode = false; - this.modulesPath = dappPath(embark.config.embarkConfig.generationDir, constants.dappArtifacts.symlinkDir); - this.registered = false; - - this.webServerConfig = embark.config.webServerConfig; - this.blockchainConfig = embark.config.blockchainConfig; - - this.setServiceCheck() - // this.embark.events.setCommandHandler("module:ipfs:reset", (cb) => { - // this.events.request("processes:stop", "ipfs", (err) => { - // if (err) { - // this.logger.error(__('Error stopping IPFS process'), err); - // } - // this.init(cb); - // }); - // }); - - // this.init(); - - this.events.on("ipfs:process:started", () => { - // this.events.on("blockchain:ready", () => { - this.registerAndSetIpfs(); - }); - - this.events.request("processes:register", "ipfs", { - launchFn: (cb) => { - // if (this.usingRunningNode) { - // return cb(__("IPFS process is running in a separate process and cannot be started by Embark.")); - // } - this.startProcess((err, newProcessStarted) => { - this.addObjectToConsole(); - this.events.emit("ipfs:process:started", err, newProcessStarted); - cb(); - }); - }, - stopFn: (cb) => { - // if (this.usingRunningNode) { - // return cb(__("IPFS process is running in a separate process and cannot be stopped by Embark.")); - // } - // this.stopProcess(cb); - } - }); - - this.events.request("processes:launch", "ipfs", (err, msg) => { - if (err) { - this.logger.error(err); - // return callback(err); - } - if (msg) { - this.logger.info(msg); - } - // callback(); - }); - - } - - addObjectToConsole() { - const {host, port} = this._getNodeUrlConfig(); - let ipfs = IpfsApi(host, port); - this.events.emit("runcode:register", "ipfs", ipfs); - - this.events.request('console:register:helpCmd', { - cmdName: "ipfs", - cmdHelp: __("instantiated js-ipfs object configured to the current environment (available if ipfs is enabled)") - }, () => { }) - - } - - // TODO: should be done in embarkjs-ipfs - // TODO: check config, etc.. - registerAndSetIpfs() { - // TODO: this should be at the start - const code = ` - const __embarkIPFS = require('embarkjs-ipfs'); - EmbarkJS.Storage.registerProvider('ipfs', __embarkIPFS.default || __embarkIPFS); - `; - - // TODO: this should be done when a connection is detected - this.events.request('runcode:eval', code, (err) => { - let providerCode = `\nEmbarkJS.Storage.setProviders(${JSON.stringify(this.embark.config.storageConfig.dappConnection || [])}, {web3});`; - this.events.request('runcode:eval', providerCode, (err) => { - }); - }); - } - - // =================== - // =================== - // =================== - // =================== - // =================== - - init(callback = () => {}) { - if (!this.isIpfsStorageEnabledInTheConfig()) { - this.events.emit("ipfs:process:started", null, false); - return callback(); - } - if (!this.registered) { - this.registered = true; - this.setServiceCheck(); - this.registerUploadCommand(); - this.listenToCommands(); - this.registerConsoleCommands(); - this.events.request("processes:register", "ipfs", { - launchFn: (cb) => { - if(this.usingRunningNode) { - return cb(__("IPFS process is running in a separate process and cannot be started by Embark.")); - } - this.startProcess((err, newProcessStarted) => { - this.addObjectToConsole(); - this.events.emit("ipfs:process:started", err, newProcessStarted); - cb(); - }); - }, - stopFn: (cb) => { - if(this.usingRunningNode) { - return cb(__("IPFS process is running in a separate process and cannot be stopped by Embark.")); - } - this.stopProcess(cb); - } - }); - } - - this.events.request("processes:launch", "ipfs", (err, msg) => { - if (err) { - this.logger.error(err); - return callback(err); - } - if (msg) { - this.logger.info(msg); - } - callback(); - }); - - // TODO: it will have the issue of waiting for the ipfs to start when the code is generator - // TODO: could be solved by having a list of services to wait on before attempting to execute code in the console - this.addStorageProviderToEmbarkJS(); - } - - downloadIpfsApi(cb) { - this.events.request("version:get:ipfs-api", (ipfsApiVersion) => { - let currentIpfsApiVersion = require('../package.json').dependencies["ipfs-api"]; - if (ipfsApiVersion === currentIpfsApiVersion) { - const nodePath = embarkPath('node_modules'); - const ipfsPath = require.resolve("ipfs-api", {paths: [nodePath]}); - return cb(null, ipfsPath); - } - this.events.request("version:getPackageLocation", "ipfs-api", ipfsApiVersion, (err, location) => { - cb(err, dappPath(location)); - }); - }); - } - - _getNodeUrlConfig() { - if (this.config.storageConfig.upload.provider === 'ipfs') { - return this.config.storageConfig.upload; - } - - for (let connection of this.config.storageConfig.dappConnection) { - if (connection.provider === 'ipfs') { - return connection; - } - } - } - - addStorageProviderToEmbarkJS() { - this.events.request('version:downloadIfNeeded', 'ipfs-api', (err, location) => { - if (err) { - this.logger.error(__('Error downloading IPFS API')); - return this.logger.error(err.message || err); - } - this.events.request('code-generator:ready', () => { - this.events.request('code-generator:symlink:generate', location, 'ipfs-api', (err, _symlinkDest) => { - if (err) { - this.logger.error(__('Error creating a symlink to IPFS API')); - return this.logger.error(err.message || err); - } - - this.events.emit('runcode:register', 'IpfsApi', require('ipfs-api'), () => { - - }); - }); - }); - - let linkedModulePath = path.join(this.modulesPath, 'embarkjs-ipfs'); - if (process.platform === 'win32') linkedModulePath = linkedModulePath.replace(/\\/g, '\\\\'); - - const code = ` - const __embarkIPFS = require('${linkedModulePath}'); - EmbarkJS.Storage.registerProvider('ipfs', __embarkIPFS.default || __embarkIPFS); - `; - - this.events.request('version:downloadIfNeeded', 'embarkjs-ipfs', (err, location) => { - if (err) { - this.logger.error(__('Error downloading embarkjs-ipfs')); - throw err; - } - this.embark.addProviderInit("storage", code, () => { return true; }); - this.embark.addConsoleProviderInit("storage", code, () => { return true; }); - this.embark.addGeneratedCode((cb) => { - return cb(null, code, `embarkjs-ipfs`, location); - }); - }); - }); - } - - startProcess(callback) { - this._checkService((err) => { - if (!err) { - this.usingRunningNode = true; - this.logger.info("IPFS node found, using currently running node"); - return callback(null, false); - } - this.logger.info("IPFS node not found, attempting to start own node"); - let self = this; - if(this.storageProcessesLauncher === null) { - this.storageProcessesLauncher = new StorageProcessesLauncher({ - logger: self.logger, - events: self.events, - storageConfig: self.config.storageConfig, - webServerConfig: self.webServerConfig, - blockchainConfig: self.blockchainConfig, - corsParts: self.embark.config.corsParts, - embark: self.embark - }); - } - self.logger.trace(`Storage module: Launching ipfs process...`); - return this.storageProcessesLauncher.launchProcess('ipfs', (err) => { - callback(err, true); - }); - }); - } - stopProcess(cb) { - if(!this.storageProcessesLauncher) return cb(); - this.storageProcessesLauncher.stopProcess("ipfs", cb); - } - - registerUploadCommand() { - const self = this; - this.embark.registerUploadCommand('ipfs', (cb) => { - let upload_ipfs = new UploadIPFS({ - buildDir: self.buildDir || 'dist/', - storageConfig: self.config.storageConfig, - configIpfsBin: self.config.storageConfig.ipfs_bin || "ipfs", - env: this.embark.env - }); - - upload_ipfs.deploy(cb); - }); - } - - listenToCommands() { - this.events.setCommandHandler('logs:ipfs:enable', (cb) => { - this.events.emit('logs:storage:enable'); - return cb(null, 'Enabling IPFS logs'); - }); - - this.events.setCommandHandler('logs:ipfs:disable', (cb) => { - this.events.emit('logs:storage:disable'); - return cb(null, 'Disabling IPFS logs'); - }); - } - - registerConsoleCommands() { - this.embark.registerConsoleCommand({ - matches: ['log ipfs on'], - process: (cmd, callback) => { - this.events.request('logs:ipfs:enable', callback); - } - }); - this.embark.registerConsoleCommand({ - matches: ['log ipfs off'], - process: (cmd, callback) => { - this.events.request('logs:ipfs:disable', callback); - } - }); - } - - isIpfsStorageEnabledInTheConfig() { - let {enabled, available_providers, dappConnection, upload} = this.config.storageConfig; - return (enabled || this.embark.currentContext.includes(constants.contexts.upload)) && - ( - available_providers.includes('ipfs') && - ( - dappConnection.some(c => c.provider === 'ipfs') || - upload.provider === 'ipfs' - ) - ); - } -} - -module.exports = IPFS; diff --git a/packages/embark-ipfs/src/index.js b/packages/embark-ipfs/src/index.js index 3dc74cca5..7c4e45025 100644 --- a/packages/embark-ipfs/src/index.js +++ b/packages/embark-ipfs/src/index.js @@ -63,9 +63,6 @@ class IPFS { this.registerEmbarkJSStorage() } - // TODO: - // * generate embarkjs storage artifact - async addEmbarkJSIpfsArtifact(params, cb) { const code = ` var EmbarkJS; diff --git a/packages/embark-storage/src/index.js b/packages/embark-storage/src/index.js index 03cadbc7e..c076ff5fb 100644 --- a/packages/embark-storage/src/index.js +++ b/packages/embark-storage/src/index.js @@ -1,5 +1,4 @@ import { __ } from 'embark-i18n'; -import * as async from 'async'; class Storage { constructor(embark, options){ @@ -14,25 +13,15 @@ class Storage { this.storageNodes = {}; this.events.setCommandHandler("storage:node:register", (clientName, startCb) => { - console.dir("---- registering " + clientName) this.storageNodes[clientName] = startCb }); this.events.setCommandHandler("storage:node:start", (storageConfig, cb) => { - console.dir("--------------------------"); - console.dir("--------------------------"); - console.dir("--------------------------"); - console.dir("--------------------------"); - console.dir("--------------------------"); - console.dir("--------------------------"); - console.dir("--- storage:node:start"); const clientName = storageConfig.upload.provider; - console.dir("---- starting...." + clientName); const client = this.storageNodes[clientName]; if (!client) return cb("storage " + clientName + " not found"); let onStart = () => { - console.dir("--- storage started") this.events.emit("storage:started", clientName); cb(); } @@ -65,61 +54,6 @@ class Storage { }, cb); } - // handleUploadCommand() { - // const self = this; - // this.embark.events.setCommandHandler('storage:upload', (cb) => { - // let platform = this.embark.config.storageConfig.upload.provider; - - // let uploadCmds = self.plugins.getPluginsProperty('uploadCmds', 'uploadCmds'); - // for (let uploadCmd of uploadCmds) { - // if (uploadCmd.cmd === platform) { - // return uploadCmd.cb.call(uploadCmd.cb, cb); - // } - // } - - // cb({message: __('platform "{{platform}}" is specified as the upload provider, however no plugins have registered an upload command for "{{platform}}".', {platform: platform})}); - // }); - // } - - // addSetProviders(cb) { - // let code = `\nEmbarkJS.Storage.setProviders(${JSON.stringify(this.embark.config.storageConfig.dappConnection || [])}, {web3});`; - - // let shouldInit = (storageConfig) => { - // return storageConfig.enabled; - // }; - - // this.embark.addProviderInit('storage', code, shouldInit); - - // async.parallel([ - // (next) => { - // if (!this.storageConfig.available_providers.includes('ipfs')) { - // return next(); - // } - // this.embark.events.once('ipfs:process:started', next); - // }, - // (next) => { - // if (!this.storageConfig.available_providers.includes('swarm')) { - // return next(); - // } - // this.embark.events.once('swarm:process:started', next); - // } - // ], (err) => { - // if (err) { - // console.error(__('Error starting storage process(es): %s', err)); - // } - - // this.embark.addConsoleProviderInit('storage', code, shouldInit); - // // TODO: fix me, this is an ugly workaround for race conditions - // // in the case where the storage process is too slow when starting up we - // // execute ourselves the setProviders because the console provider init - // // was already executed - // this.embark.events.request('runcode:eval', `if (Object.keys(EmbarkJS.Storage.Providers).length) { ${code} }`, () => { - // this.ready = true; - // this.embark.events.emit("module:storage:ready"); - // }, true); - // }); - // } - } module.exports = Storage; diff --git a/packages/embark-whisper/src/index.js b/packages/embark-whisper/src/index.js index 46f2ea666..1de482cbd 100644 --- a/packages/embark-whisper/src/index.js +++ b/packages/embark-whisper/src/index.js @@ -2,7 +2,6 @@ import { __ } from 'embark-i18n'; import {dappPath, canonicalHost, defaultHost} from 'embark-utils'; let Web3 = require('web3'); const constants = require('embark-core/constants'); -import * as path from 'path'; const API = require('./api.js'); const EMBARK_RESOURCE_ORIGIN = "http://embark"; @@ -21,203 +20,93 @@ class Whisper { this.modulesPath = dappPath(embark.config.embarkConfig.generationDir, constants.dappArtifacts.symlinkDir); this.plugins = options.plugins; - if (embark.currentContext.includes('test') && options.node &&options.node === 'vm') { - this.logger.info(__('Whisper disabled in the tests')); - return; - } - - if (!this.communicationConfig.enabled) { - return; - } - this.api = new API(embark, this.web3); this.api.registerAPICalls(); - // ================ - // TODO: - // figure out best way to detect is a node exists or launch a whisper process or wait for the blockchain process - // ================ - // this.events.on("blockchain:ready", this.executeEmbarkJSBlockchain.bind(this)); + this.events.request("runcode:whitelist", 'embarkjs', () => { }); + this.events.request("runcode:whitelist", 'embarkjs-whisper', () => { }); - this.setServiceCheck(); - - // TODO: see above, not ideal to do this, need engine.start process - // can also register service and instead react to it and connect - // this.waitForWeb3Ready(() => { - // this.registerAndSetWhisper(); - // }); - this.events.on("blockchain:ready", () => { - this.registerAndSetWhisper(); - }); + // TODO: should launch its own whisper node + // this.events.on("communication:started", this.connectEmbarkJSProvider.bind(this)); + this.events.on("blockchain:started", this.connectEmbarkJSProvider.bind(this)); let plugin = this.plugins.createPlugin('whisperplugin', {}); - plugin.registerActionForEvent("pipeline:generateAll:before", this.addArtifactFile.bind(this)); + plugin.registerActionForEvent("pipeline:generateAll:before", this.addEmbarkJSWhisperArtifact.bind(this)); - // =============================== - // this.connectToProvider(); + this.events.request("communication:node:register", "whisper", (readyCb) => { + // TODO: should launch its own whisper node + console.dir("--- whisper readyCb") + console.dir('--- registering whisper node') + // this.events.request('processes:register', 'communication', { + // launchFn: (cb) => { + // this.startProcess(cb); + // }, + // stopFn: (cb) => { this.stopProcess(cb); } + // }); + // this.events.request("processes:launch", "communication", (err) => { + readyCb() + // }); + // this.registerServiceCheck() + }); - // this.events.request('processes:register', 'whisper', (cb) => { - // this.waitForWeb3Ready(() => { - // this.web3.shh.getInfo((err) => { - // if (err) { - // const message = err.message || err; - // if (message.indexOf('not supported') > -1) { - // this.logger.error('Whisper is not supported on your node. Are you using the simulator?'); - // return this.logger.trace(message); - // } - // } - // this.setServiceCheck(); - // this.addWhisperToEmbarkJS(); - // this.addSetProvider(); - // this.registerAPICalls(); - // cb(); - // }); - // }); - // }); - - // this.events.request('processes:launch', 'whisper'); + this.registerEmbarkJSCommunication() } - // TODO: should load the latest config - addArtifactFile(_params, cb) { - let config = { - // TODO: for consistency we should change this to be dappConnection or connection - connection: this.communicationConfig.connection + async addEmbarkJSWhisperArtifact(params, cb) { + let connection = this.communicationConfig.connection || {}; + const config = { + server: canonicalHost(connection.host || defaultHost), + port: connection.port || '8546', + type: connection.type || 'ws' }; + const code = ` + var EmbarkJS; + if (typeof EmbarkJS === 'undefined') { + EmbarkJS = require('embarkjs'); + } + const __embarkWhisper = require('embarkjs-whisper'); + EmbarkJS.Messages.registerProvider('whisper', __embarkWhisper.default || __embarkWhisper); + EmbarkJS.Messages.setProvider('whisper', ${JSON.stringify(config)}); + `; this.events.request("pipeline:register", { - path: [this.embarkConfig.generationDir, 'config'], - file: 'storage.json', - format: 'json', - content: config + path: [this.embarkConfig.generationDir, 'storage'], + file: 'init.js', + format: 'js', + content: code }, cb); } - connectToProvider() { - let {host, port} = this.communicationConfig.connection; - let web3Endpoint = 'ws://' + host + ':' + port; - // Note: dont't pass to the provider things like {headers: {Origin: "embark"}}. Origin header is for browser to fill - // to protect user, it has no meaning if it is used server-side. See here for more details: https://github.com/ethereum/go-ethereum/issues/16608 - // Moreover, Parity reject origins that are not urls so if you try to connect with Origin: "embark" it gives the followin error: - // << Blocked connection to WebSockets server from untrusted origin: Some("embark") >> - // The best choice is to use void origin, BUT Geth rejects void origin, so to keep both clients happy we can use http://embark - this.web3.setProvider(new Web3.providers.WebsocketProvider(web3Endpoint, {headers: {Origin: EMBARK_RESOURCE_ORIGIN}})); - } + async registerEmbarkJSCommunication() { + let checkEmbarkJS = ` + return (typeof EmbarkJS === 'undefined'); + `; + let EmbarkJSNotDefined = await this.events.request2('runcode:eval', checkEmbarkJS); - registerAndSetWhisper() { - if (this.communicationConfig === {}) { - return; - } - if ((this.communicationConfig.available_providers.indexOf('whisper') < 0) && (this.communicationConfig.provider !== 'whisper' || this.communicationConfig.enabled !== true)) { - return; + if (EmbarkJSNotDefined) { + await this.events.request2("runcode:register", 'EmbarkJS', require('embarkjs')); } - // let linkedModulePath = path.join(this.modulesPath, 'embarkjs-whisper'); - // if (process.platform === 'win32') linkedModulePath = linkedModulePath.replace(/\\/g, '\\\\'); - - // const code = ` - // const __embarkWhisperNewWeb3 = EmbarkJS.isNode ? require('${linkedModulePath}') : require('embarkjs-whisper'); - // EmbarkJS.Messages.registerProvider('whisper', __embarkWhisperNewWeb3.default || __embarkWhisperNewWeb3); - // `; - - let code = ` - const __embarkWhisperNewWeb3 = require('embarkjs-whisper'); - EmbarkJS.Messages.registerProvider('whisper', __embarkWhisperNewWeb3.default || __embarkWhisperNewWeb3); + const registerProviderCode = ` + const __embarkWhisper = require('embarkjs-whisper'); + EmbarkJS.Messages.registerProvider('whisper', __embarkWhisper.default || __embarkWhisper); `; + await this.events.request2('runcode:eval', registerProviderCode); + } + + async connectEmbarkJSProvider() { let connection = this.communicationConfig.connection || {}; - - if (!(this.communicationConfig.provider === 'whisper' && this.communicationConfig.enabled === true)) { - return this.events.request('runcode:eval', code, () => { - }); - } - - // todo: make the add code a function as well const config = { server: canonicalHost(connection.host || defaultHost), port: connection.port || '8546', type: connection.type || 'ws' }; - code += `\nEmbarkJS.Messages.setProvider('whisper', ${JSON.stringify(config)});`; + const code = ` + EmbarkJS.Messages.setProvider('whisper', ${JSON.stringify(config)}); + `; - // this.embark.addCodeToEmbarkJS(code); - this.events.request('runcode:eval', code, (err) => { - // if (err) { - // return cb(err); - // } - }); - } - - // =============================== - // =============================== - // =============================== - // =============================== - // =============================== - // =============================== - - waitForWeb3Ready(cb) { - if (this.web3Ready) { - return cb(); - } - if (this.web3.currentProvider.connection.readyState !== 1) { - this.connectToProvider(); - return setTimeout(this.waitForWeb3Ready.bind(this, cb), 50); - } - this.web3Ready = true; - cb(); - } - - setServiceCheck() { - const self = this; - self.events.request("services:register", 'Whisper', function(cb) { - if (!self.web3.currentProvider || self.web3.currentProvider.connection.readyState !== 1) { - return self.connectToProvider(); - } - // 1) Parity does not implement shh_version JSON-RPC method - // 2) web3 1.0 still does not implement web3_clientVersion - // so we must do all by our own - self.web3._requestManager.send({method: 'web3_clientVersion', params: []}, (err, clientVersion) => { - if (err) return cb(err); - if (clientVersion.indexOf("Parity-Ethereum//v2") === 0) { - // This is Parity - return self.web3.shh.getInfo(function(err) { - if (err) { - return cb({name: 'Whisper', status: 'off'}); - } - // TOFIX Assume Whisper v6 until there's a way to understand it via JSON-RPC - return cb({name: 'Whisper (version 6)', status: 'on'}); - }); - } - // Assume it is a Geth compliant client - self.web3.shh.getVersion(function(err, version) { - if (err || version === "2") { - return cb({name: 'Whisper', status: 'off'}); - } - return cb({name: 'Whisper (version ' + version + ')', status: 'on'}); - }); - }); - }); - } - - addSetProvider() { - let connection = this.communicationConfig.connection || {}; - const shouldInit = (communicationConfig) => { - return (communicationConfig.provider === 'whisper' && communicationConfig.enabled === true); - }; - - // todo: make the add code a function as well - const config = { - server: canonicalHost(connection.host || defaultHost), - port: connection.port || '8546', - type: connection.type || 'ws' - }; - const code = `\nEmbarkJS.Messages.setProvider('whisper', ${JSON.stringify(config)});`; - - this.embark.addProviderInit('communication', code, shouldInit); - - const consoleConfig = Object.assign({}, config, {providerOptions: {headers: {Origin: EMBARK_RESOURCE_ORIGIN}}}); - const consoleCode = `\nEmbarkJS.Messages.setProvider('whisper', ${JSON.stringify(consoleConfig)});`; - this.embark.addConsoleProviderInit('communication', consoleCode, shouldInit); + await this.events.request2('runcode:eval', code); } } diff --git a/packages/embark/src/cmd/cmd_controller.js b/packages/embark/src/cmd/cmd_controller.js index 6276de81a..6f2bca94f 100644 --- a/packages/embark/src/cmd/cmd_controller.js +++ b/packages/embark/src/cmd/cmd_controller.js @@ -170,6 +170,7 @@ class EmbarkController { engine.registerModuleGroup("webserver"); engine.registerModuleGroup("filewatcher"); engine.registerModuleGroup("storage"); + engine.registerModuleGroup("communication"); engine.events.on('deployment:deployContracts:afterAll', () => { console.dir("--- generating files...") @@ -187,6 +188,10 @@ class EmbarkController { console.dir("====> requesting storage node to start...") await engine.events.request2("storage:node:start", engine.config.storageConfig, cb); }); + plugin.registerActionForEvent("embark:engine:started", async (_params, cb) => { + console.dir("====> requesting communication node to start...") + await engine.events.request2("communication:node:start", engine.config.communicationConfig, cb); + }); engine.events.request('watcher:start'); @@ -856,6 +861,8 @@ class EmbarkController { const Engine = require('../lib/core/engine.js'); const engine = new Engine({ + // TODO: we should NOT use env, it's here because it's being used somewhere deep in the code + // but we should/need to remove it as it's causing unexpected behaviour env: options.env, client: options.client, locale: options.locale, diff --git a/packages/embark/src/lib/core/engine.js b/packages/embark/src/lib/core/engine.js index 94bba6f9c..2477115f8 100644 --- a/packages/embark/src/lib/core/engine.js +++ b/packages/embark/src/lib/core/engine.js @@ -83,6 +83,7 @@ class Engine { "pipeline": this.pipelineService, "webserver": this.webserverService, "storage": this.storageComponent, + "communication": this.communicationComponents, "filewatcher": this.filewatcherService }; @@ -196,6 +197,11 @@ class Engine { this.registerModulePackage('embark-ipfs', {plugins: this.plugins}); } + communicationComponents() { + this.registerModule('communication', {plugins: this.plugins}); + this.registerModulePackage('embark-whisper', {plugins: this.plugins}); + } + startService(serviceName, _options) { let options = _options || {}; diff --git a/packages/embark/src/lib/modules/communication/index.js b/packages/embark/src/lib/modules/communication/index.js new file mode 100644 index 000000000..5bc6151f5 --- /dev/null +++ b/packages/embark/src/lib/modules/communication/index.js @@ -0,0 +1,48 @@ +import { __ } from 'embark-i18n'; + +class Communication { + constructor(embark, options){ + this.embark = embark; + this.embarkConfig = embark.config.embarkConfig; + this.events = this.embark.events; + this.communicationConfig = embark.config.communicationConfig; + this.plugins = options.plugins; + + let plugin = this.plugins.createPlugin('communicationplugin', {}); + plugin.registerActionForEvent("pipeline:generateAll:before", this.addArtifactFile.bind(this)); + + this.communicationNodes = {}; + this.events.setCommandHandler("communication:node:register", (clientName, startCb) => { + this.communicationNodes[clientName] = startCb + }); + + this.events.setCommandHandler("communication:node:start", (communicationConfig, cb) => { + const clientName = communicationConfig.provider; + const client = this.communicationNodes[clientName]; + if (!client) return cb("communication " + clientName + " not found"); + + let onStart = () => { + this.events.emit("communication:started", clientName); + cb(); + } + + client.apply(client, [onStart]); + }); + } + + addArtifactFile(_params, cb) { + let config = { + // TODO: for consistency we should change this to be dappConnection or connection + connection: this.communicationConfig.connection + } + this.events.request("pipeline:register", { + path: [this.embarkConfig.generationDir, 'config'], + file: 'communication.json', + format: 'json', + content: config + }, cb); + } + +} + +module.exports = Communication;