2
0
mirror of https://github.com/status-im/embark-area-51.git synced 2025-01-20 12:18:49 +00:00

Merge pull request from embark-framework/features/improve-storage-config

Improve storage config
This commit is contained in:
Iuri Matias 2018-06-01 12:07:30 -04:00 committed by GitHub
commit 4669922090
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 948 additions and 745 deletions

@ -231,6 +231,9 @@ EmbarkJS.Storage.setProvider = function(provider, options) {
}; };
EmbarkJS.Storage.isAvailable = function(){ EmbarkJS.Storage.isAvailable = function(){
if (!this.currentStorage) {
throw new Error('Storage provider not set; e.g EmbarkJS.Storage.setProvider("ipfs")');
}
return this.currentStorage.isAvailable(); return this.currentStorage.isAvailable();
}; };

@ -203,7 +203,7 @@ class Cmd {
.option('--loglevel [loglevel]', __('level of logging to display') + ' ["error", "warn", "info", "debug", "trace"]', /^(error|warn|info|debug|trace)$/i, 'debug') .option('--loglevel [loglevel]', __('level of logging to display') + ' ["error", "warn", "info", "debug", "trace"]', /^(error|warn|info|debug|trace)$/i, 'debug')
.option('--locale [locale]', __('language to use (default: en)')) .option('--locale [locale]', __('language to use (default: en)'))
.option('-c, --client [client]', __('Use a specific ethereum client or simulator (supported: %s)', 'geth, testrpc')) .option('-c, --client [client]', __('Use a specific ethereum client or simulator (supported: %s)', 'geth, testrpc'))
.description(__('Upload your dapp to a decentralized storage') + ' (e.g embark upload ipfs).') .description(__('Upload your dapp to a decentralized storage') + '.')
.action(function (env, _options) { .action(function (env, _options) {
i18n.setOrDetectLocale(_options.locale); i18n.setOrDetectLocale(_options.locale);
_options.env = env || 'development'; _options.env = env || 'development';

@ -120,6 +120,7 @@ Blockchain.prototype.run = function() {
return; return;
} }
args = _.compact(args); args = _.compact(args);
console.trace(`Geth command: ${cmd} ${args.join(' ')}`);
self.child = child_process.spawn(cmd, args, {cwd: process.cwd()}); self.child = child_process.spawn(cmd, args, {cwd: process.cwd()});
self.child.on('error', (err) => { self.child.on('error', (err) => {

@ -78,17 +78,27 @@ Config.prototype._updateBlockchainCors = function(){
let blockchainConfig = this.blockchainConfig; let blockchainConfig = this.blockchainConfig;
let storageConfig = this.storageConfig; let storageConfig = this.storageConfig;
let webServerConfig = this.webServerConfig; let webServerConfig = this.webServerConfig;
let cors = ''; let corsParts = [];
if(webServerConfig && webServerConfig.enabled) { if(webServerConfig && webServerConfig.enabled) {
let webServerPort = webServerConfig.port ? `:${webServerConfig.port}` : ''; if(webServerConfig.host) corsParts.push(utils.buildUrlFromConfig(webServerConfig));
if(webServerConfig.host) cors = `http://${webServerConfig.host}${webServerPort}`;
} }
if(storageConfig && storageConfig.enabled) { if(storageConfig && storageConfig.enabled) {
let storagePort = storageConfig.port ? `:${storageConfig.port}` : ''; // if getUrl is specified in the config, that needs to be included in cors
if(storageConfig.host) cors += `${cors.length ? ',' : ''}${storageConfig.protocol || 'http'}://${storageConfig.host}${storagePort}`; // 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);
corsParts.push(getUrlParts.join('/'));
}
// use our modified getUrl or in case it wasn't specified, use a built url
else{
corsParts.push(utils.buildUrlFromConfig(storageConfig.upload));
}
} }
let cors = corsParts.join(',');
if(blockchainConfig.rpcCorsDomain === 'auto' && cors.length) blockchainConfig.rpcCorsDomain = cors; if(blockchainConfig.rpcCorsDomain === 'auto' && cors.length) blockchainConfig.rpcCorsDomain = cors;
if(blockchainConfig.wsOrigins === 'auto' && cors.length) blockchainConfig.wsOrigins = cors; if(blockchainConfig.wsOrigins === 'auto' && cors.length) blockchainConfig.wsOrigins = cors;
}; };
@ -209,7 +219,7 @@ Config.prototype.loadExternalContractsFiles = function() {
}; };
Config.prototype.loadStorageConfigFile = function() { Config.prototype.loadStorageConfigFile = function() {
var versions = utils.recursiveMerge({"ipfs-api": "17.2.4"}, this.embarkConfig.versions || {}); var versions = utils.recursiveMerge({"ipfs-api": "17.2.4", "p-iteration": "1.1.7"}, this.embarkConfig.versions || {});
var configObject = { var configObject = {
"default": { "default": {
@ -217,11 +227,14 @@ Config.prototype.loadStorageConfigFile = function() {
"enabled": true, "enabled": true,
"available_providers": ["ipfs", "swarm"], "available_providers": ["ipfs", "swarm"],
"ipfs_bin": "ipfs", "ipfs_bin": "ipfs",
"provider": "ipfs", "upload": {
"protocol": "http", "provider": "ipfs",
"host": "localhost", "protocol": "http",
"port": 5001, "host": "localhost",
"getUrl": "http://localhost:8080/ipfs/" "port": 5001,
"getUrl": "http://localhost:8080/ipfs/"
},
"dappConnection": [{"provider": "ipfs", "host": "localhost", "port": 5001, "getUrl": "http://localhost:8080/ipfs/"}]
} }
}; };

@ -107,10 +107,9 @@ class Engine {
"fileWatcher": this.fileWatchService, "fileWatcher": this.fileWatchService,
"webServer": this.webServerService, "webServer": this.webServerService,
"namingSystem": this.namingSystem, "namingSystem": this.namingSystem,
"ipfs": this.ipfsService,
"web3": this.web3Service, "web3": this.web3Service,
"libraryManager": this.libraryManagerService, "libraryManager": this.libraryManagerService,
"swarm": this.swarmService "storage": this.storageService
}; };
let service = services[serviceName]; let service = services[serviceName];
@ -135,7 +134,6 @@ class Engine {
logger: this.logger, logger: this.logger,
plugins: this.plugins plugins: this.plugins
}); });
this.events.on('code-generator-ready', function () { this.events.on('code-generator-ready', function () {
self.events.request('code', function (abi, contractsJSON) { self.events.request('code', function (abi, contractsJSON) {
pipeline.build(abi, contractsJSON, null, () => { pipeline.build(abi, contractsJSON, null, () => {
@ -264,20 +262,18 @@ class Engine {
}); });
} }
ipfsService(_options) { storageService(_options) {
this.registerModule('ipfs', { this.registerModule('storage', {
addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor), addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor),
storageConfig: this.config.storageConfig,
webServerConfig: this.config.webServerConfig,
blockchainConfig: this.config.blockchainConfig,
host: _options.host, host: _options.host,
port: _options.port port: _options.port,
}); servicesMonitor: this.servicesMonitor,
} events: this.events,
logger: this.logger,
swarmService(_options) { context: this.context
this.registerModule('swarm', {
addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor),
// TODO: this should not be needed and should be deducted from the config instead
// the eth provider is not necessary the same as the swarm one
bzz: this.blockchain.web3.bzz
}); });
} }

@ -124,23 +124,42 @@
"Blockchain node is ready": "Blockchain node is ready", "Blockchain node is ready": "Blockchain node is ready",
"terminating due to error": "terminating due to error", "terminating due to error": "terminating due to error",
"Unable to start the blockchain process. Is Geth installed?": "Unable to start the blockchain process. Is Geth installed?", "Unable to start the blockchain process. Is Geth installed?": "Unable to start the blockchain process. Is Geth installed?",
"Cannot upload: {{platform}} node is not running on {{protocol}}://{{host}}:{{port}}.": "Cannot upload: {{platform}} node is not running on {{protocol}}://{{host}}:{{port}}.",
"Error while downloading the file": "Error while downloading the file", "Error while downloading the file": "Error while downloading the file",
"Error while loading the content of ": "Error while loading the content of ", "Error while loading the content of ": "Error while loading the content of ",
"no contracts found": "no contracts found", "IPFS node is offline": "IPFS node is offline",
"DApp path length is too long: \"": "DApp path length is too long: \"", "IPFS node detected": "IPFS node detected",
"This is known to cause issues with some applications, please consider reducing your DApp path's length to 66 characters or less.": "This is known to cause issues with some applications, please consider reducing your DApp path's length to 66 characters or less.", "Webserver is offline": "Webserver is offline",
"DApp path length is too long: ": "DApp path length is too long: ",
"WARNING! DApp path length is too long: ": "WARNING! DApp path length is too long: ",
"This is known to cause issues with starting geth, please consider reducing your DApp path's length to 66 characters or less.": "This is known to cause issues with starting geth, please consider reducing your DApp path's length to 66 characters or less.",
"Installing packages...": "Installing packages...", "Installing packages...": "Installing packages...",
"Next steps:": "Next steps:", "Next steps:": "Next steps:",
"open another console in the same directory and run": "open another console in the same directory and run", "open another console in the same directory and run": "open another console in the same directory and run",
"deploying to swarm!": "deploying to swarm!",
"adding %s to swarm": "adding %s to swarm",
"successfully uploaded to swarm": "successfully uploaded to swarm",
"Cannot upload: {{plaform}} node is not running on {{protocol}}://{{host}}{{port}}.": "Cannot upload: {{platform}} node is not running on {{protocol}}://{{host}}{{port}}.",
"no contracts found": "no contracts found",
"IPFS node is offline": "IPFS node is offline",
"IPFS node detected": "IPFS node detected",
"Webserver is offline": "Webserver is offline",
"DApp path length is too long: \"": "DApp path length is too long: \"",
"This is known to cause issues with some applications, please consider reducing your DApp path's length to 66 characters or less.": "This is known to cause issues with some applications, please consider reducing your DApp path's length to 66 characters or less.",
"For more info go to http://embark.status.im": "For more info go to http://embark.status.im", "For more info go to http://embark.status.im": "For more info go to http://embark.status.im",
"Cannot upload: {{platform}} node is not running on {{protocol}}://{{host}}{{port}}.": "Cannot upload: {{platform}} node is not running on {{protocol}}://{{host}}{{port}}.",
"DApp path length is too long: ": "DApp path length is too long: ",
"WARNING! DApp path length is too long: ": "WARNING! DApp path length is too long: ",
"This is known to cause issues with starting geth, please consider reducing your DApp path's length to 66 characters or less.": "This is known to cause issues with starting geth, please consider reducing your DApp path's length to 66 characters or less.",
"%s is not installed on your machine": "%s is not installed on your machine", "%s is not installed on your machine": "%s is not installed on your machine",
"You can install it by visiting: %s": "You can install it by visiting: %s", "You can install it by visiting: %s": "You can install it by visiting: %s",
"IPFS node is offline": "IPFS node is offline",
"Starting ipfs process": "Starting ipfs process", "Starting ipfs process": "Starting ipfs process",
"ipfs process started": "ipfs process started", "ipfs process started": "ipfs process started",
"IPFS node detected": "IPFS node detected" "Starting swarm process": "Starting swarm process",
"swarm process started": "swarm process started",
"Storage process for swarm ended before the end of this process. Code: 12": "Storage process for swarm ended before the end of this process. Code: 12",
"Storage process for swarm ended before the end of this process. Code: 1": "Storage process for swarm ended before the end of this process. Code: 1",
"Storage process for ipfs ended before the end of this process. Code: 12": "Storage process for ipfs ended before the end of this process. Code: 12",
"Blockchain process ended before the end of this process. Code: %s": "Blockchain process ended before the end of this process. Code: %s",
"Cannot start {{platform}} node on {{protocol}}://{{host}}{{port}}.": "Cannot start {{platform}} node on {{protocol}}://{{host}}{{port}}.",
"Cannot upload: {{platform}} node is not running on {{url}}.": "Cannot upload: {{platform}} node is not running on {{url}}.",
"Cannot start {{platform}} node on {{url}}.": "Cannot start {{platform}} node on {{url}}.",
"Storage process for swarm ended before the end of this process. Code: 0": "Storage process for swarm ended before the end of this process. Code: 0",
"error uploading to swarm": "error uploading to swarm"
} }

@ -1,8 +1,5 @@
let async = require('async'); let async = require('async');
const constants = require('./constants'); const constants = require('./constants');
const _ = require('underscore');
const StorageProcessesLauncher = require('./processes/storageProcesses/storageProcessesLauncher');
// require("./utils/debug_util.js")(__filename, async);
require('colors'); require('colors');
@ -67,42 +64,6 @@ class Embark {
templateGenerator.generate(destinationFolder, name); templateGenerator.generate(destinationFolder, name);
} }
_checkStorageEndpoint(engine, platform, callback) {
let checkFn;
_.find(engine.servicesMonitor.checkList, (value, key) => {
if(key.toLowerCase() === platform.toLowerCase()){
checkFn = value;
return true;
}
});
if (!checkFn || typeof checkFn.fn !== 'function') {
return callback();
}
checkFn.fn(function (serviceCheckResult) {
if (!serviceCheckResult.status || serviceCheckResult.status === 'off') {
return callback('No node');
}
callback();
});
}
_startStorageNode(engine, platform, callback) {
const storageProcessesLauncher = new StorageProcessesLauncher({
logger: engine.logger,
events: engine.events,
storageConfig: engine.config.storageConfig,
webServerConfig: engine.config.webServerConfig
});
return storageProcessesLauncher.launchProcess(platform.toLowerCase(), (err) => {
if (err) {
engine.logger.error(err);
return callback(err);
}
callback();
});
}
run(options) { run(options) {
let self = this; let self = this;
self.context = options.context || [constants.contexts.run, constants.contexts.build]; self.context = options.context || [constants.contexts.run, constants.contexts.build];
@ -159,10 +120,9 @@ class Embark {
engine.startService("web3"); engine.startService("web3");
engine.startService("pipeline"); engine.startService("pipeline");
engine.startService("deployment"); engine.startService("deployment");
engine.startService("storage");
engine.startService("codeGenerator"); engine.startService("codeGenerator");
engine.startService("namingSystem"); engine.startService("namingSystem");
// TODO: this should be just 'storage' and the storage should figure out the module
engine.startService(engine.config.storageConfig.provider);
engine.events.on('check:backOnline:Ethereum', function () { engine.events.on('check:backOnline:Ethereum', function () {
engine.logger.info(__('Ethereum node detected') + '..'); engine.logger.info(__('Ethereum node detected') + '..');
@ -172,20 +132,6 @@ class Embark {
}); });
}); });
// Check storage
const platform = engine.config.storageConfig.provider;
self._checkStorageEndpoint(engine, platform, (err) => {
if (!err) {
return;
}
self._startStorageNode(engine, platform, (err) => {
if (err) {
engine.logger.error('Error while starting a storage process for ' + platform);
engine.logger.error(err);
}
});
});
engine.events.on('outputDone', function () { engine.events.on('outputDone', function () {
engine.logger.info((__("Looking for documentation? You can find it at") + " ").cyan + "http://embark.status.im/docs/".green.underline + ".".cyan); engine.logger.info((__("Looking for documentation? You can find it at") + " ").cyan + "http://embark.status.im/docs/".green.underline + ".".cyan);
engine.logger.info(__("Ready").underline); engine.logger.info(__("Ready").underline);
@ -249,10 +195,8 @@ class Embark {
engine.startService("web3"); engine.startService("web3");
engine.startService("pipeline"); engine.startService("pipeline");
engine.startService("deployment", {onlyCompile: options.onlyCompile}); engine.startService("deployment", {onlyCompile: options.onlyCompile});
engine.startService("storage");
engine.startService("codeGenerator"); engine.startService("codeGenerator");
// TODO: this should be just 'storage' and the storage should figure out the modules to load
engine.startService("ipfs");
engine.startService("swarm");
callback(); callback();
}, },
function deploy(callback) { function deploy(callback) {
@ -305,6 +249,7 @@ class Embark {
engine.startService("libraryManager"); engine.startService("libraryManager");
engine.startService("pipeline"); engine.startService("pipeline");
engine.startService("deployment", {onlyCompile: true}); engine.startService("deployment", {onlyCompile: true});
engine.startService("codeGenerator"); engine.startService("codeGenerator");
engine.events.request('deploy:contracts', function(err) { engine.events.request('deploy:contracts', function(err) {
@ -335,7 +280,6 @@ class Embark {
} }
upload(options) { upload(options) {
const self = this;
this.context = options.context || [constants.contexts.upload, constants.contexts.build]; this.context = options.context || [constants.contexts.upload, constants.contexts.build];
let engine = new Engine({ let engine = new Engine({
@ -351,11 +295,12 @@ class Embark {
events: options.events, events: options.events,
logger: options.logger, logger: options.logger,
config: options.config, config: options.config,
plugins: options.plugins plugins: options.plugins,
context: this.context
}); });
engine.init(); engine.init();
let platform = engine.config.storageConfig.provider; let platform = engine.config.storageConfig.upload.provider;
let cmdPlugin; let cmdPlugin;
async.waterfall([ async.waterfall([
@ -367,35 +312,11 @@ class Embark {
engine.startService("web3"); engine.startService("web3");
engine.startService("pipeline"); engine.startService("pipeline");
engine.startService("deployment"); engine.startService("deployment");
engine.startService("storage");
engine.startService("codeGenerator"); engine.startService("codeGenerator");
// TODO: this should be just 'storage' and the storage should figure out the modules to load
engine.startService(platform.toLowerCase());
engine.startMonitor(); engine.startMonitor();
callback(); callback();
}, },
function checkStorageService(callback){
const errorObj = {message: __('Cannot upload: {{platform}} node is not running on {{protocol}}://{{host}}:{{port}}.', {platform: platform, protocol: engine.config.storageConfig.protocol, host: engine.config.storageConfig.host, port: engine.config.storageConfig.port})};
self._checkStorageEndpoint(engine, platform, function (err) {
if (!err) {
return callback();
}
self._startStorageNode(engine, platform, (err) => {
if (err) {
engine.logger.error(err);
return callback(errorObj);
}
// Check endpoint again to see if really did start
self._checkStorageEndpoint(engine, platform, (err) => {
if (err) {
return callback(errorObj);
}
callback();
});
});
});
},
function setupStoragePlugin(callback){ function setupStoragePlugin(callback){
let pluginList = engine.plugins.listPlugins(); let pluginList = engine.plugins.listPlugins();
if (pluginList.length > 0) { if (pluginList.length > 0) {
@ -413,8 +334,7 @@ class Embark {
}); });
} }
if (!cmdPlugin) { if (!cmdPlugin) {
engine.logger.info(__('try "{{ipfs}}" or "{{swarm}}"', {ipfs: 'embark upload ipfs', swarm: 'embark upload swarm'}).green); return callback({message: __('platform "{{platform}}" is specified as the upload provider, however no plugins have registered an upload command for "{{platform}}".', {platform: platform})});
return callback({message: 'unknown platform: ' + platform});
} }
callback(); callback();
}, },

@ -7,23 +7,24 @@ __embarkIPFS.setProvider = function (options) {
var promise = new Promise(function (resolve, reject) { var promise = new Promise(function (resolve, reject) {
try { try {
if (options === undefined) { if (options === undefined) {
self.ipfsConnection = IpfsApi('localhost', '5001'); self._config = options;
self._ipfsConnection = IpfsApi('localhost', '5001');
self._getUrl = "http://localhost:8080/ipfs/"; self._getUrl = "http://localhost:8080/ipfs/";
} else { } else {
var ipfsOptions = {host: options.server, protocol: 'http'}; var ipfsOptions = {host: options.host || options.server, protocol: 'http'};
if (options.protocol) { if (options.protocol) {
ipfsOptions.protocol = options.protocol; ipfsOptions.protocol = options.protocol;
} }
if (options.port && options.port !== 'false') { if (options.port && options.port !== 'false') {
ipfsOptions.port = options.port; ipfsOptions.port = options.port;
} }
self.ipfsConnection = IpfsApi(ipfsOptions); self._ipfsConnection = IpfsApi(ipfsOptions);
self._getUrl = options.getUrl || "http://localhost:8080/ipfs/"; self._getUrl = options.getUrl || "http://localhost:8080/ipfs/";
} }
resolve(self); resolve(self);
} catch (err) { } catch (err) {
console.log(err); console.error(err);
self.ipfsConnection = null; self._ipfsConnection = null;
reject(new Error('Failed to connect to IPFS')); reject(new Error('Failed to connect to IPFS'));
} }
}); });
@ -33,11 +34,11 @@ __embarkIPFS.setProvider = function (options) {
__embarkIPFS.saveText = function (text) { __embarkIPFS.saveText = function (text) {
const self = this; const self = this;
var promise = new Promise(function (resolve, reject) { var promise = new Promise(function (resolve, reject) {
if (!self.ipfsConnection) { if (!self._ipfsConnection) {
var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()'); var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()');
reject(connectionError); reject(connectionError);
} }
self.ipfsConnection.add(self.ipfsConnection.Buffer.from(text), function (err, result) { self._ipfsConnection.add(self._ipfsConnection.Buffer.from(text), function (err, result) {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {
@ -54,11 +55,11 @@ __embarkIPFS.get = function (hash) {
// TODO: detect type, then convert if needed // TODO: detect type, then convert if needed
//var ipfsHash = web3.toAscii(hash); //var ipfsHash = web3.toAscii(hash);
var promise = new Promise(function (resolve, reject) { var promise = new Promise(function (resolve, reject) {
if (!self.ipfsConnection) { if (!self._ipfsConnection) {
var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()'); var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()');
reject(connectionError); reject(connectionError);
} }
self.ipfsConnection.get(hash, function (err, files) { self._ipfsConnection.get(hash, function (err, files) {
if (err) { if (err) {
return reject(err); return reject(err);
} }
@ -78,15 +79,15 @@ __embarkIPFS.uploadFile = function (inputSelector) {
} }
var promise = new Promise(function (resolve, reject) { var promise = new Promise(function (resolve, reject) {
if (!self.ipfsConnection) { if (!self._ipfsConnection) {
var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()'); var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()');
reject(connectionError); reject(connectionError);
} }
var reader = new FileReader(); var reader = new FileReader();
reader.onloadend = function () { reader.onloadend = function () {
var fileContent = reader.result; var fileContent = reader.result;
var buffer = self.ipfsConnection.Buffer.from(fileContent); var buffer = self._ipfsConnection.Buffer.from(fileContent);
self.ipfsConnection.add(buffer, function (err, result) { self._ipfsConnection.add(buffer, function (err, result) {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {
@ -102,10 +103,10 @@ __embarkIPFS.uploadFile = function (inputSelector) {
__embarkIPFS.isAvailable = function () { __embarkIPFS.isAvailable = function () {
return new Promise((resolve) => { return new Promise((resolve) => {
if (!this.ipfsConnection) { if (!this._ipfsConnection) {
return resolve(false); return resolve(false);
} }
this.ipfsConnection.id() this._ipfsConnection.id()
.then((id) => { .then((id) => {
resolve(Boolean(id)); resolve(Boolean(id));
}) })
@ -119,3 +120,4 @@ __embarkIPFS.getUrl = function (hash) {
return (this._getUrl || "http://localhost:8080/ipfs/") + hash; return (this._getUrl || "http://localhost:8080/ipfs/") + hash;
}; };

@ -1,7 +1,8 @@
let UploadIPFS = require('./upload.js'); const UploadIPFS = require('./upload.js');
let utils = require('../../utils/utils.js'); const utils = require('../../utils/utils.js');
let fs = require('../../core/fs.js'); const fs = require('../../core/fs.js');
let IpfsApi = require('ipfs-api'); const IpfsApi = require('ipfs-api');
const _ = require('underscore');
class IPFS { class IPFS {
@ -9,23 +10,18 @@ class IPFS {
this.logger = embark.logger; this.logger = embark.logger;
this.events = embark.events; this.events = embark.events;
this.buildDir = options.buildDir; this.buildDir = options.buildDir;
this.storageConfig = embark.config.storageConfig; this.storageConfig = options.storageConfig;
this.host = options.host || this.storageConfig.host; this.host = options.host || this.storageConfig.upload.host;
this.port = options.port || this.storageConfig.port; this.port = options.port || this.storageConfig.upload.port;
this.protocol = options.protocol || this.storageConfig.upload.protocol;
this.addCheck = options.addCheck; this.addCheck = options.addCheck;
this.embark = embark; this.embark = embark;
this.commandlineDeploy();
this.setServiceCheck();
this.addIPFSToEmbarkJS();
this.addSetProvider();
this.addIpfsObjectToConsole();
} }
commandlineDeploy() { commandlineDeploy() {
let upload_ipfs = new UploadIPFS({ let upload_ipfs = new UploadIPFS({
buildDir: this.buildDir || 'dist/', buildDir: this.buildDir || 'dist/',
storageConfig: this.storageConfig, storageConfig: this.storageConfig.upload,
configIpfsBin: this.storageConfig.ipfs_bin || "ipfs" configIpfsBin: this.storageConfig.ipfs_bin || "ipfs"
}); });
@ -40,7 +36,7 @@ class IPFS {
if (!storageConfig.enabled) { if (!storageConfig.enabled) {
return; return;
} }
if (storageConfig.provider !== 'ipfs' && storageConfig.available_providers.indexOf("ipfs") < 0) { if (_.findWhere(this.storageConfig.dappConnection, {'provider': 'ipfs'}) === undefined && (storageConfig.upload.provider !== 'ipfs' || storageConfig.available_providers.indexOf("ipfs") < 0)) {
return; return;
} }
@ -58,7 +54,13 @@ class IPFS {
self.addCheck('IPFS', function (cb) { self.addCheck('IPFS', function (cb) {
self.logger.trace("Checking IPFS version..."); self.logger.trace("Checking IPFS version...");
utils.httpGetJson('http://' + self.host + ':' + self.port + '/api/v0/version', function (err, body) { let url = (self.protocol || 'http') + '://' + self.host + ':' + self.port + '/api/v0/version';
if(self.protocol !== 'https'){
utils.httpGetJson(url, versionCb);
} else {
utils.httpsGetJson(url, versionCb);
}
function versionCb(err, body) {
if (err) { if (err) {
self.logger.trace("Check IPFS version error: " + err); self.logger.trace("Check IPFS version error: " + err);
return cb({name: "IPFS ", status: 'off'}); return cb({name: "IPFS ", status: 'off'});
@ -67,18 +69,18 @@ class IPFS {
return cb({name: ("IPFS " + body.Version), status: 'on'}); return cb({name: ("IPFS " + body.Version), status: 'on'});
} }
return cb({name: "IPFS ", status: 'on'}); return cb({name: "IPFS ", status: 'on'});
}); }
}); });
} }
addIPFSToEmbarkJS() { addProviderToEmbarkJS() {
const self = this; const self = this;
// TODO: make this a shouldAdd condition // TODO: make this a shouldAdd condition
if (this.storageConfig === {}) { if (this.storageConfig === {}) {
return; return;
} }
if ((this.storageConfig.available_providers.indexOf('ipfs') < 0) && (this.storageConfig.provider !== 'ipfs' || this.storageConfig.enabled !== true)) { if (this.storageConfig.available_providers.indexOf('ipfs') < 0 || _.findWhere(this.storageConfig.dappConnection, {'provider': 'ipfs'}) === undefined || this.storageConfig.enabled !== true) {
return; return;
} }
@ -91,6 +93,15 @@ class IPFS {
} }
}); });
self.events.request("version:get:p-iteration", function(pIterationVersion) {
let currentPIterationVersion = require('../../../package.json').dependencies["p-iteration"];
if (pIterationVersion !== currentPIterationVersion) {
self.events.request("version:getPackageLocation", "p-iteration", pIterationVersion, function(err, location) {
self.embark.registerImportFile("p-iteration", fs.dappPath(location));
});
}
});
let code = ""; let code = "";
code += "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString(); code += "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString();
code += "\nEmbarkJS.Storage.registerProvider('ipfs', __embarkIPFS);"; code += "\nEmbarkJS.Storage.registerProvider('ipfs', __embarkIPFS);";
@ -98,24 +109,8 @@ class IPFS {
this.embark.addCodeToEmbarkJS(code); this.embark.addCodeToEmbarkJS(code);
} }
addSetProvider() { addObjectToConsole() {
let config = JSON.stringify({ let ipfs = IpfsApi(this.host, this.port);
server: this.storageConfig.host,
port: this.storageConfig.port,
protocol: this.storageConfig.protocol,
getUrl: this.storageConfig.getUrl
});
let code = "\nEmbarkJS.Storage.setProvider('ipfs'," + config + ");";
let shouldInit = (storageConfig) => {
return (storageConfig.provider === 'ipfs' && storageConfig.enabled === true);
};
this.embark.addProviderInit('storage', code, shouldInit);
}
addIpfsObjectToConsole() {
let ipfs = IpfsApi(this.storageConfig.host, this.storageConfig.port);
this.events.emit("runcode:register", "ipfs", ipfs); this.events.emit("runcode:register", "ipfs", ipfs);
} }

@ -44,7 +44,7 @@ class IPFS {
}, },
function printUrls(dir_hash, callback) { function printUrls(dir_hash, callback) {
console.log(("=== " + __("DApp available at") + " http://localhost:8080/ipfs/" + dir_hash + "/").green); console.log(("=== " + __("DApp available at") + " http://localhost:8080/ipfs/" + dir_hash + "/").green);
console.log(("=== " + __("DApp available at") + " http://gateway.ipfs.io/ipfs/" + dir_hash + "/").green); console.log(("=== " + __("DApp available at") + " http://ipfs.infura.io/ipfs/" + dir_hash + "/").green);
callback(); callback();
} }

@ -55,6 +55,7 @@ class SpecialConfigs {
self.replaceWithAddresses(cmd, nextMapCb); self.replaceWithAddresses(cmd, nextMapCb);
}, (err, result) => { }, (err, result) => {
if (err) { if (err) {
self.logger.trace(err);
return cb(new Error("error running afterDeploy")); return cb(new Error("error running afterDeploy"));
} }
let onDeployCode = result; let onDeployCode = result;

@ -0,0 +1,36 @@
/* global EmbarkJS */
import {findSeries} from 'p-iteration';
let __embarkStorage = {};
__embarkStorage.setProviders = async function (dappConnOptions) {
try {
let workingConnFound = await findSeries(dappConnOptions, async (dappConn) => {
if(dappConn === '$BZZ' || dappConn.provider === 'swarm'){
let options = dappConn;
if(dappConn === '$BZZ') options = {"useOnlyGivenProvider": true};
try{
await EmbarkJS.Storage.setProvider('swarm', options);
let isAvailable = await EmbarkJS.Storage.isAvailable();
return isAvailable;
}catch(err){
return false; // catch errors for when bzz object not initialised but config has requested it to be used
}
}
else if(dappConn.provider === 'ipfs') {
// set the provider then check the connection, if true, use that provider, else, check next provider
try{
await EmbarkJS.Storage.setProvider('ipfs', dappConn);
let isAvailable = await EmbarkJS.Storage.isAvailable();
return isAvailable;
} catch(err) {
return false;
}
}
});
if(!workingConnFound) throw new Error('Could not connect to a storage provider using any of the dappConnections in the storage config');
} catch (err) {
throw new Error('Failed to connect to a storage provider: ' + err.message);
}
};

@ -0,0 +1,217 @@
const utils = require('../../utils/utils.js');
const fs = require('../../core/fs.js');
const _ = require('underscore');
const async = require('async');
const StorageProcessesLauncher = require('../../processes/storageProcesses/storageProcessesLauncher');
const constants = require('../../constants');
class Storage {
constructor(embark, options){
this._embark = embark;
this._options = options;
this._storageConfig = options.storageConfig;
this._webServerConfig = options.webServerConfig;
this._blockchainConfig = options.blockchainConfig;
this._servicesMonitor = options.servicesMonitor;
this._events = options.events;
this._logger = options.logger;
// filter list of dapp connections based on available_providers set in config
let hasSwarm = _.contains(this._storageConfig.available_providers, 'swarm'); // don't need to eval this in every loop iteration
// contains valid dapp storage providers
this._validDappProviders = _.filter(this._storageConfig.dappConnection, (conn) => {
return _.contains(this._storageConfig.available_providers, conn.provider) || (conn === '$BZZ' && hasSwarm);
});
this.initStorageForEmbark();
this.initStorageForDapp();
// don't start storage processes on build command, only on upload or run
if(_.contains(options.context, constants.contexts.upload) || _.contains(options.context, constants.contexts.run)){
this.startStorageProcesses();
}
}
_checkStorageEndpoint(platform, callback) {
let checkFn;
let self = this;
self._logger.trace(`Storage module: Checking ${platform} availability...`);
_.find(self._servicesMonitor.checkList, (value, key) => {
if(key.toLowerCase() === platform.toLowerCase()){
checkFn = value;
return true;
}
});
if (!checkFn || typeof checkFn.fn !== 'function') {
self._logger.trace(`Storage module: Check for ${platform} node does not exist.`);
return callback();
}
checkFn.fn(function (serviceCheckResult) {
if (!serviceCheckResult.status || serviceCheckResult.status === 'off') {
self._logger.trace(`Storage module: ${platform} node not available.`);
return callback('No node');
}
callback();
});
}
_startStorageNode(platform, callback) {
let self = this;
const storageProcessesLauncher = new StorageProcessesLauncher({
logger: self._logger,
events: self._events,
storageConfig: self._storageConfig,
webServerConfig: self._webServerConfig,
blockchainConfig: self._blockchainConfig
});
self._logger.trace(`Storage module: Launching ${platform} process...`);
return storageProcessesLauncher.launchProcess(platform.toLowerCase(), (err) => {
if (err) {
self._logger.error(err);
return callback(err);
}
callback();
});
}
/// Initializes a storage provider for Embark upload
initStorageForEmbark(){
let storageProviderCls = require(`../${this._storageConfig.upload.provider}/index.js`);
let uploadProvider = new storageProviderCls(this._embark, this._options); /*eslint no-new: "off"*/
if(typeof uploadProvider.commandlineDeploy == 'function') uploadProvider.commandlineDeploy();
if(typeof uploadProvider.setServiceCheck == 'function') uploadProvider.setServiceCheck();
if(typeof uploadProvider.addObjectToConsole == 'function') uploadProvider.addObjectToConsole();
}
/**
* Initializes a storage provider for EmbarkJS
*
* @return {void}
*/
initStorageForDapp(){
// now we need to add instantiate any dappConnection/available_providers storage providers to add
// their provider code to embarkjs
this._validDappProviders.forEach(dappConn => {
if(!dappConn.provider) return;
let storageProviderCls = require(`../${dappConn.provider}/index.js`);
// override options with dappConnection settings
let storageOptions = this._options;
storageOptions.protocol = dappConn.protocol;
storageOptions.host = dappConn.host;
storageOptions.port = dappConn.port;
// then instantiate the storage provdier class
let storageProvider = new storageProviderCls(this._embark, storageOptions); /*eslint no-new: "off"*/
// register the service check so we can use it to check if the process is running before spawning it
// check that it hasn't already been done above
if(dappConn.provider !== this._storageConfig.upload.provider){
if(typeof storageProvider.setServiceCheck == 'function') storageProvider.setServiceCheck();
}
// add __embarkSwarm and __embarkIPFS objects to EmbarkJS
if(typeof storageProvider.addProviderToEmbarkJS == 'function') storageProvider.addProviderToEmbarkJS();
});
// add the storage provider code (__embarkStorage) to embarkjs
this.addProviderToEmbarkJS();
// add the code to call setProviders in embarkjs after embark is ready
this.addSetProviders();
}
/**
* Adds the storage provider code (__embarkStorage) to embarkjs
*
* @returns {void}
*/
addProviderToEmbarkJS(){
// TODO: make this a shouldAdd condition
if (this._storageConfig === {} || !this._storageConfig.dappConnection || !this._storageConfig.dappConnection.length) {
return;
}
let code = "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString();
this._embark.addCodeToEmbarkJS(code);
}
/**
* Adds the code to call setProviders in embarkjs after embark is ready
*
* @returns {void}
*/
addSetProviders() {
let code = `\n__embarkStorage.setProviders(${JSON.stringify(this._validDappProviders)});`;
let shouldInit = (storageConfig) => {
return (this._validDappProviders !== undefined && this._validDappProviders.length > 0 && storageConfig.enabled === true);
};
this._embark.addProviderInit('storage', code, shouldInit);
}
startStorageProcesses(){
let platform = this._storageConfig.upload.provider;
let self = this;
async.waterfall([
function checkStorageService(callback){
const errorObj = {message: __('Cannot upload: {{platform}} node is not running on {{url}}.', {platform: platform, url: utils.buildUrlFromConfig(self._storageConfig.upload)})};
// start the upload storage node
self._checkStorageEndpoint(platform, function (err) {
if (!err) {
return callback();
}
self._startStorageNode(platform, (err) => {
if (err) {
self._logger.error(err);
return callback(errorObj);
}
// Check endpoint again to see if really did start
self._checkStorageEndpoint(platform, (err) => {
if (err) {
return callback(errorObj);
}
callback();
});
});
});
},
function checkDappConnectionStorageService(callback){
// start any dappConnection storage nodes
self._validDappProviders.forEach(dappConn => {
if(!dappConn.provider || dappConn.provider === platform) return; // don't start the process we've just started above
const errorObj = {message: __('Cannot start {{platform}} node on {{url}}.', {platform: dappConn.provider, url: utils.buildUrlFromConfig(dappConn)})};
self._checkStorageEndpoint(dappConn.provider, function (err) {
if (!err) {
return callback();
}
self._startStorageNode(dappConn.provider, (err) => {
if (err) {
self._logger.error(err);
return callback(errorObj);
}
// Check endpoint again to see if really did start
self._checkStorageEndpoint(dappConn.provider, (err) => {
if (err) {
return callback(errorObj);
}
callback();
});
});
});
});
}
]);
}
}
module.exports = Storage;

@ -3,36 +3,47 @@ let __embarkSwarm = {};
const bytes = require("eth-lib/lib/bytes"); const bytes = require("eth-lib/lib/bytes");
__embarkSwarm.setProvider = function (options) { __embarkSwarm.setProvider = function (options) {
this.bzz = web3.bzz; let protocol = options.protocol || 'http';
this.protocol = options.protocol; let port = options.port ? `:${options.port}` : '';
this.host = options.host;
this.port = options.port; this._config = options;
this.connectUrl = `${options.protocol}://${options.host}:${options.port}`; this._connectUrl = `${protocol}://${options.host}${port}`;
this.connectError = new Error(`Cannot connect to Swarm node on ${this.connectUrl}`); this._connectError = new Error(`Cannot connect to Swarm node on ${this._connectUrl}`);
this._getUrl = options.getUrl || `${this.connectUrl}/bzzr:/`;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
if (!this.bzz.currentProvider) { if (!web3.bzz.currentProvider && !options.useOnlyGivenProvider) {
this.bzz.setProvider(`${options.protocol}://${options.host}:${options.port}`); web3.bzz.setProvider(this._connectUrl);
}
else if(options.useOnlyGivenProvider && web3.bzz.givenProvider !== null){
web3.bzz.setProvider(web3.bzz.givenProvider);
} }
resolve(this); resolve(this);
} catch (err) { } catch (err) {
console.log(err); console.log(err);
reject(this.connectError); reject(this._connectError);
} }
}); });
}; };
__embarkSwarm.isAvailable = function () { __embarkSwarm.isAvailable = function () {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!this.bzz) { // if web3 swarm object doesn't exist
if (!web3.bzz) {
return resolve(false); return resolve(false);
} }
this.bzz.isAvailable() // swarm obj exists, but has no provider set (seems to happen a LOT!),
// try setting the provider to our currently set provider again
else if(!web3.bzz.currentProvider && this._config.host){
web3.bzz.setProvider(this._connectUrl);
}
if (!web3.bzz.currentProvider) {
return resolve(false);
}
web3.bzz.isAvailable()
.then(resolve) .then(resolve)
.catch(() => { .catch(() => {
reject(this.connectError); reject(this._connectError);
}); });
}); });
}; };
@ -41,9 +52,9 @@ __embarkSwarm.saveText = function (text) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.isAvailable().then((isAvailable) => { this.isAvailable().then((isAvailable) => {
if (!isAvailable) { if (!isAvailable) {
return reject(this.connectError); return reject(this._connectError);
} }
this.bzz.upload(text) web3.bzz.upload(text)
.then(resolve) .then(resolve)
.catch(reject); .catch(reject);
}).catch(reject); }).catch(reject);
@ -54,9 +65,9 @@ __embarkSwarm.get = function (hash) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.isAvailable().then((isAvailable) => { this.isAvailable().then((isAvailable) => {
if (!isAvailable) { if (!isAvailable) {
return reject(this.connectError); return reject(this._connectError);
} }
this.bzz.download(hash) web3.bzz.download(hash)
.then((uint8Array) => resolve(bytes.toString(bytes.fromUint8Array(uint8Array)))) .then((uint8Array) => resolve(bytes.toString(bytes.fromUint8Array(uint8Array))))
.catch(reject); .catch(reject);
}).catch(reject); }).catch(reject);
@ -76,9 +87,9 @@ __embarkSwarm.uploadFile = function (inputSelector) {
const fileContent = new Uint8Array(event.target.result); const fileContent = new Uint8Array(event.target.result);
this.isAvailable().then((isAvailable) => { this.isAvailable().then((isAvailable) => {
if (!isAvailable) { if (!isAvailable) {
return reject(this.connectError); return reject(this._connectError);
} }
this.bzz.upload(fileContent) web3.bzz.upload(fileContent)
.then(resolve) .then(resolve)
.catch(reject); .catch(reject);
}).catch(reject); }).catch(reject);
@ -89,6 +100,6 @@ __embarkSwarm.uploadFile = function (inputSelector) {
}; };
__embarkSwarm.getUrl = function (hash) { __embarkSwarm.getUrl = function (hash) {
return this._getUrl + hash; return `${this._config.getUrl || this._connectUrl + '/bzz:/'}${hash}`;
}; };

@ -1,6 +1,8 @@
let UploadSwarm = require('./upload.js'); const UploadSwarm = require('./upload.js');
let utils = require('../../utils/utils.js'); const utils = require('../../utils/utils.js');
let fs = require('../../core/fs.js'); const fs = require('../../core/fs.js');
const Web3Bzz = require('web3-bzz');
const _ = require('underscore');
class Swarm { class Swarm {
@ -8,30 +10,22 @@ class Swarm {
this.logger = embark.logger; this.logger = embark.logger;
this.events = embark.events; this.events = embark.events;
this.buildDir = options.buildDir; this.buildDir = options.buildDir;
this.storageConfig = embark.config.storageConfig; this.storageConfig = options.storageConfig;
this.host = options.host || this.storageConfig.host;
this.port = options.port || this.storageConfig.port;
this.addCheck = options.addCheck; this.addCheck = options.addCheck;
this.embark = embark; this.embark = embark;
this.bzz = options.bzz;
this.initSwarmProvider(); this.providerUrl = utils.buildUrl(options.protocol || options.storageConfig.upload.protocol, options.host || options.storageConfig.upload.host, options.port || options.storageConfig.upload.port);
this.commandlineDeploy();
this.setServiceCheck();
this.addSwarmToEmbarkJS();
this.addSetProvider();
}
initSwarmProvider(){ this.getUrl = options.storageConfig.upload.getUrl || this.providerUrl + '/bzz:/';
if(!this.bzz.currentProvider) {
this.bzz.setProvider(`http://${this.host}:${this.port}`); this.bzz = new Web3Bzz(this.providerUrl);
}
} }
commandlineDeploy() { commandlineDeploy() {
this.upload_swarm = new UploadSwarm({ this.upload_swarm = new UploadSwarm({
buildDir: this.buildDir || 'dist/', buildDir: this.buildDir || 'dist/',
storageConfig: this.storageConfig, storageConfig: this.storageConfig,
getUrl: this.getUrl,
bzz: this.bzz bzz: this.bzz
}); });
@ -47,7 +41,7 @@ class Swarm {
if (!storageConfig.enabled) { if (!storageConfig.enabled) {
return; return;
} }
if (storageConfig.provider !== 'swarm' && storageConfig.available_providers.indexOf("swarm") < 0) { if (_.findWhere(this.storageConfig.dappConnection, {'provider': 'swarm'}) === undefined && (storageConfig.upload.provider !== 'swarm' || storageConfig.available_providers.indexOf("swarm") < 0)) {
return; return;
} }
@ -75,38 +69,32 @@ class Swarm {
}); });
} }
addSwarmToEmbarkJS() { addProviderToEmbarkJS() {
let self = this;
// TODO: make this a shouldAdd condition // TODO: make this a shouldAdd condition
if (this.storageConfig === {}) { if (this.storageConfig === {}) {
return; return;
} }
if ((this.storageConfig.available_providers.indexOf('swarm') < 0) && (this.storageConfig.provider !== 'swarm' || this.storageConfig.enabled !== true)) { if (this.storageConfig.available_providers.indexOf('swarm') < 0 || _.findWhere(this.storageConfig.dappConnection, {'provider': 'swarm'}) === undefined || this.storageConfig.enabled !== true) {
return; return;
} }
this.events.request("version:get:p-iteration", function(pIterationVersion) {
let currentPIterationVersion = require('../../../package.json').dependencies["p-iteration"];
if (pIterationVersion !== currentPIterationVersion) {
self.events.request("version:getPackageLocation", "p-iteration", pIterationVersion, function(err, location) {
self.embark.registerImportFile("p-iteration", fs.dappPath(location));
});
}
});
let code = ""; let code = "";
code += "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString(); code += "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString();
code += "\nEmbarkJS.Storage.registerProvider('swarm', __embarkSwarm);"; code += "\nEmbarkJS.Storage.registerProvider('swarm', __embarkSwarm);";
this.embark.addCodeToEmbarkJS(code); this.embark.addCodeToEmbarkJS(code);
} }
addSetProvider() {
let config = JSON.stringify({
host: this.storageConfig.host,
port: this.storageConfig.port,
protocol: this.storageConfig.protocol,
getUrl: this.storageConfig.getUrl
});
let code = "\nEmbarkJS.Storage.setProvider('swarm'," + config + ");";
let shouldInit = (storageConfig) => {
return (storageConfig.provider === 'swarm' && storageConfig.enabled === true);
};
this.embark.addProviderInit('storage', code, shouldInit);
}
} }
module.exports = Swarm; module.exports = Swarm;

@ -7,6 +7,7 @@ class Swarm {
this.buildDir = options.buildDir || 'dist/'; this.buildDir = options.buildDir || 'dist/';
this.bzz = options.bzz; this.bzz = options.bzz;
this.storageConfig = options.storageConfig; this.storageConfig = options.storageConfig;
this.getUrl = options.getUrl;
} }
deploy() { deploy() {
@ -31,7 +32,8 @@ class Swarm {
if (!dir_hash) { if (!dir_hash) {
return callback('No directory hash was returned'); return callback('No directory hash was returned');
} }
console.log(("=== " + __("DApp available at") + `${self.storageConfig.getUrl}${dir_hash}/`).green); console.log(("=== " + __("DApp available at") + ` ${self.getUrl}${dir_hash}/`).green);
console.log(("=== " + __("DApp available at") + ` http://swarm-gateways.net/bzz:/${dir_hash}`).green);
callback(); callback();
} }

@ -8,6 +8,8 @@ class IPFSProcess extends ProcessWrapper {
constructor(_options) { constructor(_options) {
super(); super();
this.cors = _options.cors;
this.checkIPFSVersion(); this.checkIPFSVersion();
this.startIPFSDaemon(); this.startIPFSDaemon();
} }
@ -31,6 +33,8 @@ class IPFSProcess extends ProcessWrapper {
startIPFSDaemon() { startIPFSDaemon() {
const self = this; const self = this;
// spawn the daemon (muhaha)
this.child = child_process.spawn('ipfs', ['daemon']); this.child = child_process.spawn('ipfs', ['daemon']);
this.child.on('error', (err) => { this.child.on('error', (err) => {
@ -45,7 +49,41 @@ class IPFSProcess extends ProcessWrapper {
data = data.toString(); data = data.toString();
if (!self.readyCalled && data.indexOf('Daemon is ready') > -1) { if (!self.readyCalled && data.indexOf('Daemon is ready') > -1) {
self.readyCalled = true; self.readyCalled = true;
self.send({result: constants.storage.initiated});
// update IPFS cors before spawning a daemon (muhaha)
console.log(`RUNNING IPFS CORS UPDATE COMMAND: ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin "[\\"${self.cors.join('\\", \\"')}\\"]"`);
child_process.exec(`ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin "[\\"${self.cors.join('\\", \\"')}\\"]"`, {silent: true}, (err, stdout, _stderr) => {
if(err){
err = err.toString();
console.error('IPFS CORS update error: ', err);
}
if(_stderr){
_stderr = _stderr.toString();
console.error(`IPFS CORS update error: ${_stderr}`);
}
child_process.exec('ipfs config --json API.HTTPHeaders.Access-Control-Allow-Credentials "[\\"true\\"]"', {silent: true}, (err, stdout, _stderr) => {
if(err){
err = err.toString();
console.error('IPFS CORS update error: ', err);
}
if(_stderr){
_stderr = _stderr.toString();
console.error(`IPFS CORS update error: ${_stderr}`);
}
child_process.exec('ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods "[\\"PUT\\", \\"POST\\", \\"GET\\"]"', {silent: true}, (err, stdout, _stderr) => {
if(err){
err = err.toString();
console.error('IPFS CORS update error: ', err);
}
if(_stderr){
_stderr = _stderr.toString();
console.error(`IPFS CORS update error: ${_stderr}`);
}
self.send({result: constants.storage.initiated});
});
});
});
} }
console.log('IPFS: ' + data); console.log('IPFS: ' + data);
}); });
@ -54,6 +92,8 @@ class IPFSProcess extends ProcessWrapper {
console.error('IPFS exited with error code ' + code); console.error('IPFS exited with error code ' + code);
} }
}); });
} }
kill() { kill() {

@ -9,8 +9,11 @@ class StorageProcessesLauncher {
this.events = options.events; this.events = options.events;
this.storageConfig = options.storageConfig; this.storageConfig = options.storageConfig;
this.webServerConfig = options.webServerConfig; this.webServerConfig = options.webServerConfig;
this.blockchainConfig = options.blockchainConfig;
this.processes = {}; this.processes = {};
this.cors = this.buildCors();
this.events.on('exit', () => { this.events.on('exit', () => {
Object.keys(this.processes).forEach(processName => { Object.keys(this.processes).forEach(processName => {
this.processes[processName].send('exit'); this.processes[processName].send('exit');
@ -18,6 +21,53 @@ class StorageProcessesLauncher {
}); });
} }
buildCors(storageName)
{
let corsParts = [];
// add our webserver CORS
if(this.webServerConfig.enabled){
if (this.webServerConfig && this.webServerConfig.host) {
corsParts.push(utils.buildUrlFromConfig(this.webServerConfig));
}
else corsParts.push('http://localhost:8000');
}
// add all dapp connection storage
if(this.storageConfig.enabled) {
this.storageConfig.dappConnection.forEach(dappConn => {
if(dappConn.provider === storageName) return; // do not add CORS URL for ourselves
if(dappConn.getUrl || dappConn.host){
// if getUrl is specified in the config, that needs to be included in cors
// instead of the concatenated protocol://host:port
if(dappConn.getUrl) {
// remove /ipfs or /bzz: from getUrl if it's there
let getUrlParts = dappConn.getUrl.split('/');
getUrlParts = getUrlParts.slice(0, 3);
corsParts.push(getUrlParts.join('/'));
}
// in case getUrl wasn't specified, use a built url
else{
corsParts.push(utils.buildUrlFromConfig(dappConn));
}
}
});
}
if(this.blockchainConfig.enabled) {
// add our rpc endpoints to CORS
if(this.blockchainConfig.rpcHost && this.blockchainConfig.rpcPort){
corsParts.push(`http://${this.blockchainConfig.rpcHost}:${this.blockchainConfig.rpcPort}`);
}
// add our ws endpoints to CORS
if(this.blockchainConfig.wsRPC && this.blockchainConfig.wsHost && this.blockchainConfig.wsPort){
corsParts.push(`ws://${this.blockchainConfig.wsHost}:${this.blockchainConfig.wsPort}`);
}
}
return corsParts;
}
processExited(storageName, code) { processExited(storageName, code) {
this.logger.error(__(`Storage process for ${storageName} ended before the end of this process. Code: ${code}`)); this.logger.error(__(`Storage process for ${storageName} ended before the end of this process. Code: ${code}`));
} }
@ -37,13 +87,13 @@ class StorageProcessesLauncher {
modulePath: filePath, modulePath: filePath,
logger: self.logger, logger: self.logger,
events: self.events, events: self.events,
silent: true, silent: self.logger.logLevel !== 'trace',
exitCallback: self.processExited.bind(this, storageName) exitCallback: self.processExited.bind(this, storageName)
}); });
self.processes[storageName].send({ self.processes[storageName].send({
action: constants.blockchain.init, options: { action: constants.blockchain.init, options: {
storageConfig: self.storageConfig, storageConfig: self.storageConfig,
webServerConfig: self.webServerConfig cors: self.buildCors(storageName)
} }
}); });

@ -9,7 +9,7 @@ class SwarmProcess extends ProcessWrapper {
constructor(options) { constructor(options) {
super(); super();
this.storageConfig = options.storageConfig; this.storageConfig = options.storageConfig;
this.webServerConfig = options.webServerConfig; this.cors = options.cors;
} }
startSwarmDaemon() { startSwarmDaemon() {
@ -17,16 +17,13 @@ class SwarmProcess extends ProcessWrapper {
if (!this.storageConfig.account || !this.storageConfig.account.address || !this.storageConfig.account.password) { if (!this.storageConfig.account || !this.storageConfig.account.address || !this.storageConfig.account.password) {
return 'Account address and password are needed in the storage config to start the Swarm process'; return 'Account address and password are needed in the storage config to start the Swarm process';
} }
let corsDomain = 'http://localhost:8000';
if (self.webServerConfig && self.webServerConfig && self.webServerConfig.host && self.webServerConfig.port) {
corsDomain = `http://${self.webServerConfig.host}:${self.webServerConfig.port}`;
}
const args = [ const args = [
`--bzzaccount=${this.storageConfig.account.address}`, `--bzzaccount=${this.storageConfig.account.address}`,
`--password=${fs.dappPath(this.storageConfig.account.password)}`, `--password=${fs.dappPath(this.storageConfig.account.password)}`,
`--corsdomain=${corsDomain}` `--corsdomain=${self.cors.join(',')}`
]; ];
console.trace('Starting swarm process with arguments: ' + args.join(' '));
this.child = child_process.spawn(this.storageConfig.swarmPath || 'swarm', args); this.child = child_process.spawn(this.storageConfig.swarmPath || 'swarm', args);
this.child.on('error', (err) => { this.child.on('error', (err) => {

@ -69,6 +69,17 @@ function httpGetJson(url, callback) {
}); });
} }
function httpsGetJson(url, callback) {
httpGetRequest(https, url, function(err, body) {
try {
let parsed = JSON.parse(body);
return callback(err, parsed);
} catch(e) {
return callback(e);
}
});
}
function runCmd(cmd, options) { function runCmd(cmd, options) {
let result = shelljs.exec(cmd, options || {silent: true}); let result = shelljs.exec(cmd, options || {silent: true});
if (result.code !== 0) { if (result.code !== 0) {
@ -199,6 +210,39 @@ function normalizeInput(input) {
}).toString() + ']'); }).toString() + ']');
} }
/**
* Builds a URL
*
* @param {string} protocol
* The URL protocol, defaults to http.
* @param {string} host
* The URL host, required.
* @param {string} port
* The URL port, default to empty string.
* @returns {string} the constructued URL, with defaults
*/
function buildUrl (protocol, host, port){
if(!host) throw new Error('utils.buildUrl: parameter \'host\' is required');
if(port) port = ':' + port;
else port = '';
return `${protocol || 'http'}://${host}${port}`;
}
/**
* Builds a URL
*
* @param {object} configObj Object containing protocol, host, and port to be used to construct the url.
* * protocol {String} (optional) The URL protocol, defaults to http.
* * host {String} (required) The URL host.
* * 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');
return this.buildUrl(configObj.protocol, configObj.host, configObj.port);
}
module.exports = { module.exports = {
joinPath: joinPath, joinPath: joinPath,
filesMatchingPattern: filesMatchingPattern, filesMatchingPattern: filesMatchingPattern,
@ -208,6 +252,7 @@ module.exports = {
httpGet: httpGet, httpGet: httpGet,
httpsGet: httpsGet, httpsGet: httpsGet,
httpGetJson: httpGetJson, httpGetJson: httpGetJson,
httpsGetJson: httpsGetJson,
runCmd: runCmd, runCmd: runCmd,
cd: cd, cd: cd,
sed: sed, sed: sed,
@ -219,5 +264,7 @@ module.exports = {
getExternalContractUrl, getExternalContractUrl,
toChecksumAddress: toChecksumAddress, toChecksumAddress: toChecksumAddress,
sha3: sha3, sha3: sha3,
normalizeInput normalizeInput,
buildUrl,
buildUrlFromConfig
}; };

@ -23,15 +23,17 @@ class LibraryManager {
let solcVersionInConfig = this.contractsConfig.versions.solc; let solcVersionInConfig = this.contractsConfig.versions.solc;
let web3VersionInConfig = this.contractsConfig.versions["web3"]; let web3VersionInConfig = this.contractsConfig.versions["web3"];
let ipfsApiVersion = this.storageConfig.versions["ipfs-api"]; let ipfsApiVersion = this.storageConfig.versions["ipfs-api"];
let pIterationVersion = this.storageConfig.versions["p-iteration"];
this.versions['solc'] = solcVersionInConfig; this.versions['solc'] = solcVersionInConfig;
this.versions['web3'] = web3VersionInConfig; this.versions['web3'] = web3VersionInConfig;
this.versions['ipfs-api'] = ipfsApiVersion; this.versions['ipfs-api'] = ipfsApiVersion;
this.versions['p-iteration'] = pIterationVersion;
Object.keys(this.versions).forEach(versionKey => { Object.keys(this.versions).forEach(versionKey => {
const newVersion = this.versions[versionKey].trim(); const newVersion = this.versions[versionKey].trim();
if (newVersion !== this.versions[versionKey]) { if (newVersion !== this.versions[versionKey]) {
this.embark.logger.warn(__('There a a space in the version of {{versionKey}}. We corrected it for you ({{correction}}).', {versionKey: versionKey, correction: `"${this.versions[versionKey]}" => "${newVersion}"`})); this.embark.logger.warn(__('There is a space in the version of {{versionKey}}. We corrected it for you ({{correction}}).', {versionKey: versionKey, correction: `"${this.versions[versionKey]}" => "${newVersion}"`}));
this.versions[versionKey] = newVersion; this.versions[versionKey] = newVersion;
} }
}); });

769
package-lock.json generated

@ -434,6 +434,22 @@
} }
} }
}, },
"aproba": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
"optional": true
},
"are-we-there-yet": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
"integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
"optional": true,
"requires": {
"delegates": "1.0.0",
"readable-stream": "2.3.5"
}
},
"argparse": { "argparse": {
"version": "1.0.10", "version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@ -1626,7 +1642,7 @@
"browserify-zlib": { "browserify-zlib": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
"integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=",
"requires": { "requires": {
"pako": "1.0.6" "pako": "1.0.6"
} }
@ -1847,7 +1863,7 @@
"anymatch": "2.0.0", "anymatch": "2.0.0",
"async-each": "1.0.1", "async-each": "1.0.1",
"braces": "2.3.2", "braces": "2.3.2",
"fsevents": "1.2.4", "fsevents": "1.2.3",
"glob-parent": "3.1.0", "glob-parent": "3.1.0",
"inherits": "2.0.3", "inherits": "2.0.3",
"is-binary-path": "1.0.1", "is-binary-path": "1.0.1",
@ -2232,6 +2248,11 @@
"date-now": "0.1.4" "date-now": "0.1.4"
} }
}, },
"console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
},
"constants-browserify": { "constants-browserify": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
@ -2644,6 +2665,12 @@
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
}, },
"deep-extend": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz",
"integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==",
"optional": true
},
"deep-is": { "deep-is": {
"version": "0.1.3", "version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@ -2716,6 +2743,12 @@
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
}, },
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
"optional": true
},
"depd": { "depd": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@ -2743,6 +2776,12 @@
"repeating": "2.0.1" "repeating": "2.0.1"
} }
}, },
"detect-libc": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
"optional": true
},
"detect-node": { "detect-node": {
"version": "2.0.3", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz",
@ -2781,7 +2820,7 @@
"domain-browser": { "domain-browser": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
"integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto="
}, },
"drbg.js": { "drbg.js": {
"version": "1.0.1", "version": "1.0.1",
@ -2889,7 +2928,7 @@
"errno": { "errno": {
"version": "0.1.7", "version": "0.1.7",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
"integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=",
"requires": { "requires": {
"prr": "1.0.1" "prr": "1.0.1"
} }
@ -4218,465 +4257,13 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
}, },
"fsevents": { "fsevents": {
"version": "1.2.4", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.3.tgz",
"integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", "integrity": "sha512-X+57O5YkDTiEQGiw8i7wYc2nQgweIekqkepI8Q3y4wVlurgBt2SuwxTeYUYMZIGpLZH3r/TsMjczCMXE5ZOt7Q==",
"optional": true, "optional": true,
"requires": { "requires": {
"nan": "2.9.2", "nan": "2.9.2",
"node-pre-gyp": "0.10.0" "node-pre-gyp": "0.9.1"
},
"dependencies": {
"abbrev": {
"version": "1.1.1",
"bundled": true,
"optional": true
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true
},
"aproba": {
"version": "1.2.0",
"bundled": true,
"optional": true
},
"are-we-there-yet": {
"version": "1.1.4",
"bundled": true,
"optional": true,
"requires": {
"delegates": "1.0.0",
"readable-stream": "2.3.6"
}
},
"balanced-match": {
"version": "1.0.0",
"bundled": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"requires": {
"balanced-match": "1.0.0",
"concat-map": "0.0.1"
}
},
"chownr": {
"version": "1.0.1",
"bundled": true,
"optional": true
},
"code-point-at": {
"version": "1.1.0",
"bundled": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true
},
"core-util-is": {
"version": "1.0.2",
"bundled": true,
"optional": true
},
"debug": {
"version": "2.6.9",
"bundled": true,
"optional": true,
"requires": {
"ms": "2.0.0"
}
},
"deep-extend": {
"version": "0.5.1",
"bundled": true,
"optional": true
},
"delegates": {
"version": "1.0.0",
"bundled": true,
"optional": true
},
"detect-libc": {
"version": "1.0.3",
"bundled": true,
"optional": true
},
"fs-minipass": {
"version": "1.2.5",
"bundled": true,
"optional": true,
"requires": {
"minipass": "2.2.4"
}
},
"fs.realpath": {
"version": "1.0.0",
"bundled": true,
"optional": true
},
"gauge": {
"version": "2.7.4",
"bundled": true,
"optional": true,
"requires": {
"aproba": "1.2.0",
"console-control-strings": "1.1.0",
"has-unicode": "2.0.1",
"object-assign": "4.1.1",
"signal-exit": "3.0.2",
"string-width": "1.0.2",
"strip-ansi": "3.0.1",
"wide-align": "1.1.2"
}
},
"glob": {
"version": "7.1.2",
"bundled": true,
"optional": true,
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
"inherits": "2.0.3",
"minimatch": "3.0.4",
"once": "1.4.0",
"path-is-absolute": "1.0.1"
}
},
"has-unicode": {
"version": "2.0.1",
"bundled": true,
"optional": true
},
"iconv-lite": {
"version": "0.4.21",
"bundled": true,
"optional": true,
"requires": {
"safer-buffer": "2.1.2"
}
},
"ignore-walk": {
"version": "3.0.1",
"bundled": true,
"optional": true,
"requires": {
"minimatch": "3.0.4"
}
},
"inflight": {
"version": "1.0.6",
"bundled": true,
"optional": true,
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
}
},
"inherits": {
"version": "2.0.3",
"bundled": true
},
"ini": {
"version": "1.3.5",
"bundled": true,
"optional": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"requires": {
"number-is-nan": "1.0.1"
}
},
"isarray": {
"version": "1.0.0",
"bundled": true,
"optional": true
},
"minimatch": {
"version": "3.0.4",
"bundled": true,
"requires": {
"brace-expansion": "1.1.11"
}
},
"minimist": {
"version": "0.0.8",
"bundled": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"requires": {
"safe-buffer": "5.1.1",
"yallist": "3.0.2"
}
},
"minizlib": {
"version": "1.1.0",
"bundled": true,
"optional": true,
"requires": {
"minipass": "2.2.4"
}
},
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"requires": {
"minimist": "0.0.8"
}
},
"ms": {
"version": "2.0.0",
"bundled": true,
"optional": true
},
"needle": {
"version": "2.2.0",
"bundled": true,
"optional": true,
"requires": {
"debug": "2.6.9",
"iconv-lite": "0.4.21",
"sax": "1.2.4"
}
},
"node-pre-gyp": {
"version": "0.10.0",
"bundled": true,
"optional": true,
"requires": {
"detect-libc": "1.0.3",
"mkdirp": "0.5.1",
"needle": "2.2.0",
"nopt": "4.0.1",
"npm-packlist": "1.1.10",
"npmlog": "4.1.2",
"rc": "1.2.7",
"rimraf": "2.6.2",
"semver": "5.5.0",
"tar": "4.4.1"
}
},
"nopt": {
"version": "4.0.1",
"bundled": true,
"optional": true,
"requires": {
"abbrev": "1.1.1",
"osenv": "0.1.5"
}
},
"npm-bundled": {
"version": "1.0.3",
"bundled": true,
"optional": true
},
"npm-packlist": {
"version": "1.1.10",
"bundled": true,
"optional": true,
"requires": {
"ignore-walk": "3.0.1",
"npm-bundled": "1.0.3"
}
},
"npmlog": {
"version": "4.1.2",
"bundled": true,
"optional": true,
"requires": {
"are-we-there-yet": "1.1.4",
"console-control-strings": "1.1.0",
"gauge": "2.7.4",
"set-blocking": "2.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true
},
"object-assign": {
"version": "4.1.1",
"bundled": true,
"optional": true
},
"once": {
"version": "1.4.0",
"bundled": true,
"requires": {
"wrappy": "1.0.2"
}
},
"os-homedir": {
"version": "1.0.2",
"bundled": true,
"optional": true
},
"os-tmpdir": {
"version": "1.0.2",
"bundled": true,
"optional": true
},
"osenv": {
"version": "0.1.5",
"bundled": true,
"optional": true,
"requires": {
"os-homedir": "1.0.2",
"os-tmpdir": "1.0.2"
}
},
"path-is-absolute": {
"version": "1.0.1",
"bundled": true,
"optional": true
},
"process-nextick-args": {
"version": "2.0.0",
"bundled": true,
"optional": true
},
"rc": {
"version": "1.2.7",
"bundled": true,
"optional": true,
"requires": {
"deep-extend": "0.5.1",
"ini": "1.3.5",
"minimist": "1.2.0",
"strip-json-comments": "2.0.1"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"bundled": true,
"optional": true
}
}
},
"readable-stream": {
"version": "2.3.6",
"bundled": true,
"optional": true,
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "2.0.0",
"safe-buffer": "5.1.1",
"string_decoder": "1.1.1",
"util-deprecate": "1.0.2"
}
},
"rimraf": {
"version": "2.6.2",
"bundled": true,
"optional": true,
"requires": {
"glob": "7.1.2"
}
},
"safe-buffer": {
"version": "5.1.1",
"bundled": true
},
"safer-buffer": {
"version": "2.1.2",
"bundled": true,
"optional": true
},
"sax": {
"version": "1.2.4",
"bundled": true,
"optional": true
},
"semver": {
"version": "5.5.0",
"bundled": true,
"optional": true
},
"set-blocking": {
"version": "2.0.0",
"bundled": true,
"optional": true
},
"signal-exit": {
"version": "3.0.2",
"bundled": true,
"optional": true
},
"string-width": {
"version": "1.0.2",
"bundled": true,
"requires": {
"code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0",
"strip-ansi": "3.0.1"
}
},
"string_decoder": {
"version": "1.1.1",
"bundled": true,
"optional": true,
"requires": {
"safe-buffer": "5.1.1"
}
},
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"requires": {
"ansi-regex": "2.1.1"
}
},
"strip-json-comments": {
"version": "2.0.1",
"bundled": true,
"optional": true
},
"tar": {
"version": "4.4.1",
"bundled": true,
"optional": true,
"requires": {
"chownr": "1.0.1",
"fs-minipass": "1.2.5",
"minipass": "2.2.4",
"minizlib": "1.1.0",
"mkdirp": "0.5.1",
"safe-buffer": "5.1.1",
"yallist": "3.0.2"
}
},
"util-deprecate": {
"version": "1.0.2",
"bundled": true,
"optional": true
},
"wide-align": {
"version": "1.1.2",
"bundled": true,
"optional": true,
"requires": {
"string-width": "1.0.2"
}
},
"wrappy": {
"version": "1.0.2",
"bundled": true
},
"yallist": {
"version": "3.0.2",
"bundled": true
}
} }
}, },
"fstream": { "fstream": {
@ -4700,6 +4287,48 @@
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="
}, },
"gauge": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"optional": true,
"requires": {
"aproba": "1.2.0",
"console-control-strings": "1.1.0",
"has-unicode": "2.0.1",
"object-assign": "4.1.1",
"signal-exit": "3.0.2",
"string-width": "1.0.2",
"strip-ansi": "3.0.1",
"wide-align": "1.1.2"
},
"dependencies": {
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"optional": true,
"requires": {
"code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0",
"strip-ansi": "3.0.1"
}
}
}
},
"generate-function": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
"integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ="
},
"generate-object-property": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
"integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
"requires": {
"is-property": "1.0.2"
}
},
"get-caller-file": { "get-caller-file": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz",
@ -5208,6 +4837,12 @@
"has-symbol-support-x": "1.4.2" "has-symbol-support-x": "1.4.2"
} }
}, },
"has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
"optional": true
},
"has-value": { "has-value": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
@ -5484,6 +5119,15 @@
"integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==",
"dev": true "dev": true
}, },
"ignore-walk": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz",
"integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==",
"optional": true,
"requires": {
"minimatch": "3.0.4"
}
},
"ignorefs": { "ignorefs": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/ignorefs/-/ignorefs-1.2.0.tgz", "resolved": "https://registry.npmjs.org/ignorefs/-/ignorefs-1.2.0.tgz",
@ -5541,6 +5185,12 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}, },
"ini": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
"optional": true
},
"inquirer": { "inquirer": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
@ -6097,7 +5747,7 @@
"json-loader": { "json-loader": {
"version": "0.5.7", "version": "0.5.7",
"resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
"integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==" "integrity": "sha1-3KFKcCNf+C8KyaOr62DTN6NlGF0="
}, },
"json-parse-better-errors": { "json-parse-better-errors": {
"version": "1.0.1", "version": "1.0.1",
@ -7454,6 +7104,17 @@
} }
} }
}, },
"needle": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.2.1.tgz",
"integrity": "sha512-t/ZswCM9JTWjAdXS9VpvqhI2Ct2sL2MdY4fUXqGJaGBk13ge99ObqRksRTbBE56K+wxUXwwfZYOuZHifFW9q+Q==",
"optional": true,
"requires": {
"debug": "2.6.9",
"iconv-lite": "0.4.19",
"sax": "1.2.4"
}
},
"negotiator": { "negotiator": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
@ -7512,7 +7173,7 @@
"node-libs-browser": { "node-libs-browser": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz",
"integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", "integrity": "sha1-X5QmPUBPbkR2fXJpAf/wVHjWAN8=",
"requires": { "requires": {
"assert": "1.4.1", "assert": "1.4.1",
"browserify-zlib": "0.2.0", "browserify-zlib": "0.2.0",
@ -7544,6 +7205,83 @@
"resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-1.3.0.tgz", "resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-1.3.0.tgz",
"integrity": "sha512-/IHFGoMJWIAcFbrI3KYx6TUmHdBXRZXACAVbkHzYB39JZzoVqgme7wcMnhrOwCvrO8HfIipFTBhELJFMhiw1mg==" "integrity": "sha512-/IHFGoMJWIAcFbrI3KYx6TUmHdBXRZXACAVbkHzYB39JZzoVqgme7wcMnhrOwCvrO8HfIipFTBhELJFMhiw1mg=="
}, },
"node-pre-gyp": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.9.1.tgz",
"integrity": "sha1-8RwHUW3ZL4cZnbx+GDjqt81WyeA=",
"optional": true,
"requires": {
"detect-libc": "1.0.3",
"mkdirp": "0.5.1",
"needle": "2.2.1",
"nopt": "4.0.1",
"npm-packlist": "1.1.10",
"npmlog": "4.1.2",
"rc": "1.2.7",
"rimraf": "2.6.2",
"semver": "5.5.0",
"tar": "4.4.2"
},
"dependencies": {
"minipass": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.3.tgz",
"integrity": "sha512-/jAn9/tEX4gnpyRATxgHEOV6xbcyxgT7iUnxo9Y3+OB0zX00TgKIv/2FZCf5brBbICcwbLqVv2ImjvWWrQMSYw==",
"optional": true,
"requires": {
"safe-buffer": "5.1.2",
"yallist": "3.0.2"
}
},
"nopt": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
"integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
"optional": true,
"requires": {
"abbrev": "1.1.1",
"osenv": "0.1.5"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"tar": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.2.tgz",
"integrity": "sha512-BfkE9CciGGgDsATqkikUHrQrraBCO+ke/1f6SFAEMnxyyfN9lxC+nW1NFWMpqH865DhHIy9vQi682gk1X7friw==",
"optional": true,
"requires": {
"chownr": "1.0.1",
"fs-minipass": "1.2.5",
"minipass": "2.3.3",
"minizlib": "1.1.0",
"mkdirp": "0.5.1",
"safe-buffer": "5.1.2",
"yallist": "3.0.2"
}
},
"yallist": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
"integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k="
}
}
},
"node-webcrypto-ossl": {
"version": "1.0.35",
"resolved": "https://registry.npmjs.org/node-webcrypto-ossl/-/node-webcrypto-ossl-1.0.35.tgz",
"integrity": "sha512-KsdlCw0hTmSa4bos7BzEa7Ag9qsDgFAMi/X+Wq+OMpKjjEPZ+JQZKmuU2leiI4dXC6i8RpdGTRFRiw9bvxk8/w==",
"optional": true,
"requires": {
"mkdirp": "0.5.1",
"nan": "2.9.2",
"tslib": "1.9.0",
"webcrypto-core": "0.1.19"
}
},
"nodeify": { "nodeify": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/nodeify/-/nodeify-1.0.1.tgz", "resolved": "https://registry.npmjs.org/nodeify/-/nodeify-1.0.1.tgz",
@ -7596,6 +7334,22 @@
"sort-keys": "1.1.2" "sort-keys": "1.1.2"
} }
}, },
"npm-bundled": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz",
"integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==",
"optional": true
},
"npm-packlist": {
"version": "1.1.10",
"resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz",
"integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==",
"optional": true,
"requires": {
"ignore-walk": "3.0.1",
"npm-bundled": "1.0.3"
}
},
"npm-run-path": { "npm-run-path": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@ -7604,6 +7358,18 @@
"path-key": "2.0.1" "path-key": "2.0.1"
} }
}, },
"npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"optional": true,
"requires": {
"are-we-there-yet": "1.1.4",
"console-control-strings": "1.1.0",
"gauge": "2.7.4",
"set-blocking": "2.0.0"
}
},
"num2fraction": { "num2fraction": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
@ -7814,7 +7580,7 @@
"os-locale": { "os-locale": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
"integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=",
"requires": { "requires": {
"execa": "0.7.0", "execa": "0.7.0",
"lcid": "1.0.0", "lcid": "1.0.0",
@ -7826,6 +7592,16 @@
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
}, },
"osenv": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
"optional": true,
"requires": {
"os-homedir": "1.0.2",
"os-tmpdir": "1.0.2"
}
},
"p-cancelable": { "p-cancelable": {
"version": "0.3.0", "version": "0.3.0",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz",
@ -7836,6 +7612,11 @@
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
}, },
"p-iteration": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/p-iteration/-/p-iteration-1.1.7.tgz",
"integrity": "sha512-VsYvUPjm2edbKkX4QzlASC1qB2e4Z6IE9WPaRVHKwCtobmB6vfUcU9eBOwj1k5uMNi8O6w89QfsDatO5ePSjQg=="
},
"p-limit": { "p-limit": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz",
@ -7868,7 +7649,7 @@
"pako": { "pako": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
"integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" "integrity": "sha1-AQEhG6pwxLykoPY/Igbpe3368lg="
}, },
"parse-asn1": { "parse-asn1": {
"version": "5.1.0", "version": "5.1.0",
@ -8858,6 +8639,26 @@
"unpipe": "1.0.0" "unpipe": "1.0.0"
} }
}, },
"rc": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz",
"integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==",
"optional": true,
"requires": {
"deep-extend": "0.5.1",
"ini": "1.3.5",
"minimist": "1.2.0",
"strip-json-comments": "2.0.1"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"optional": true
}
}
},
"read": { "read": {
"version": "1.0.7", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
@ -10214,8 +10015,7 @@
"strip-json-comments": { "strip-json-comments": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
"dev": true
}, },
"style-loader": { "style-loader": {
"version": "0.19.1", "version": "0.19.1",
@ -11523,13 +11323,22 @@
} }
} }
}, },
"webcrypto-core": {
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-0.1.19.tgz",
"integrity": "sha512-RyaWaYYwFUeWVB1ny8Oj53UQJppNLyz+RWFv0IPP8W6l95kFS+jHS+4vH42o3VJaiom5EIogwmngY57Bwy5DDQ==",
"optional": true,
"requires": {
"tslib": "1.9.0"
}
},
"webcrypto-shim": { "webcrypto-shim": {
"version": "github:dignifiedquire/webcrypto-shim#190bc9ec341375df6025b17ae12ddb2428ea49c8" "version": "github:dignifiedquire/webcrypto-shim#190bc9ec341375df6025b17ae12ddb2428ea49c8"
}, },
"webpack": { "webpack": {
"version": "3.11.0", "version": "3.11.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz",
"integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==", "integrity": "sha1-d9pFGx17SxF62vQaGpO1dC8k2JQ=",
"requires": { "requires": {
"acorn": "5.5.3", "acorn": "5.5.3",
"acorn-dynamic-import": "2.0.2", "acorn-dynamic-import": "2.0.2",
@ -11597,7 +11406,7 @@
"webpack-sources": { "webpack-sources": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz",
"integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", "integrity": "sha1-oQHrrlnWUHNU1x2AE5UKOot6WlQ=",
"requires": { "requires": {
"source-list-map": "2.0.0", "source-list-map": "2.0.0",
"source-map": "0.6.1" "source-map": "0.6.1"
@ -11606,7 +11415,7 @@
"source-map": { "source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM="
} }
} }
}, },
@ -11642,6 +11451,28 @@
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
}, },
"wide-align": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
"integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
"optional": true,
"requires": {
"string-width": "1.0.2"
},
"dependencies": {
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"optional": true,
"requires": {
"code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0",
"strip-ansi": "3.0.1"
}
}
}
},
"window-size": { "window-size": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/window-size/-/window-size-1.1.0.tgz", "resolved": "https://registry.npmjs.org/window-size/-/window-size-1.1.0.tgz",

@ -54,6 +54,7 @@
"live-plugin-manager": "https://github.com/iurimatias/live-plugin-manager.git", "live-plugin-manager": "https://github.com/iurimatias/live-plugin-manager.git",
"merge": "^1.2.0", "merge": "^1.2.0",
"os-locale": "^2.1.0", "os-locale": "^2.1.0",
"p-iteration": "^1.1.7",
"parse-json": "^4.0.0", "parse-json": "^4.0.0",
"promptly": "^2.1.0", "promptly": "^2.1.0",
"propose": "0.0.5", "propose": "0.0.5",

@ -4,14 +4,21 @@
"ipfs_bin": "ipfs", "ipfs_bin": "ipfs",
"provider": "ipfs", "provider": "ipfs",
"available_providers": ["ipfs"], "available_providers": ["ipfs"],
"host": "localhost", "upload": {
"port": 5001 "host": "localhost",
"port": 5001
},
"dappConnection": [
{"provider": "ipfs", "host": "localhost", "port": 5001, "getUrl": "http://localhost:8080/ipfs/"}
]
}, },
"development": { "development": {
"enabled": true, "enabled": true,
"provider": "ipfs", "provider": "ipfs",
"host": "localhost", "upload": {
"port": 5001, "host": "localhost",
"getUrl": "http://localhost:8080/ipfs/" "port": 5001,
"getUrl": "http://localhost:8080/ipfs/"
}
} }
} }

@ -11,7 +11,8 @@
"versions": { "versions": {
"web3": "1.0.0-beta", "web3": "1.0.0-beta",
"solc": "0.4.23", "solc": "0.4.23",
"ipfs-api": "17.2.4" "ipfs-api": "17.2.4",
"p-iteration": "1.1.7"
}, },
"plugins": {} "plugins": {}
} }

@ -4,14 +4,21 @@
"ipfs_bin": "ipfs", "ipfs_bin": "ipfs",
"provider": "ipfs", "provider": "ipfs",
"available_providers": ["ipfs"], "available_providers": ["ipfs"],
"host": "localhost", "upload": {
"port": 5001 "host": "localhost",
"port": 5001
},
"dappConnection": [
{"provider": "ipfs", "host": "localhost", "port": 5001, "getUrl": "http://localhost:8080/ipfs/"}
]
}, },
"development": { "development": {
"enabled": true, "enabled": true,
"provider": "ipfs", "provider": "ipfs",
"host": "localhost", "upload": {
"port": 5001, "host": "localhost",
"getUrl": "http://localhost:8080/ipfs/" "port": 5001,
"getUrl": "http://localhost:8080/ipfs/"
}
} }
} }

@ -10,7 +10,8 @@
"versions": { "versions": {
"web3": "1.0.0-beta", "web3": "1.0.0-beta",
"solc": "0.4.23", "solc": "0.4.23",
"ipfs-api": "17.2.4" "ipfs-api": "17.2.4",
"p-iteration": "1.1.7"
}, },
"plugins": { "plugins": {
} }

@ -17,7 +17,7 @@ describe("SimpleStorage", function() {
it("set storage value", async function() { it("set storage value", async function() {
await SimpleStorage.methods.set(150).send(); await SimpleStorage.methods.set(150).send();
let result = SimpleStorage.methods.get().call(); let result = await SimpleStorage.methods.get().call();
assert.equal(result, 150); assert.equal(result, 150);
}); });

@ -1,25 +1,39 @@
{ {
"default": { "default": {
"enabled": true, "enabled": true,
"available_providers": ["ipfs", "swarm"],
"ipfs_bin": "ipfs", "ipfs_bin": "ipfs",
"provider": "ipfs",
"host": "localhost", "available_providers": ["ipfs", "swarm"],
"port": 5001
"upload": {
"provider": "ipfs",
"host": "localhost",
"port": 5001
},
"dappConnection": [
"$BZZ",
{"provider": "swarm", "host": "localhost", "port": 8500, "getUrl": "http://localhost:8500/bzzr:/"},
{"provider": "ipfs", "host": "localhost", "port": 5001, "getUrl": "http://localhost:8080/ipfs/"}
]
}, },
"development": { "development": {
"enabled": true, "enabled": true,
"provider": "swarm", "upload": {
"host": "swarm-gateways.net", "provider": "swarm",
"port": false, "host": "localhost",
"getUrl": "http://swarm-gateways.net/bzzr:/" "port": 8500,
"getUrl": "http://localhost:8500/bzzr:/"
}
}, },
"livenet": { "livenet": {
"enabled": true, "enabled": true,
"provider": "ipfs", "upload":{
"host": "ipfs.infura.io", "provider": "ipfs",
"protocol": "https", "host": "ipfs.infura.io",
"port": false, "protocol": "https",
"getUrl": "https://ipfs.infura.io/ipfs/" "port": false,
"getUrl": "https://ipfs.infura.io/ipfs/"
}
} }
} }

@ -17,7 +17,8 @@
"versions": { "versions": {
"solc": "0.4.18", "solc": "0.4.18",
"web3": "1.0.0-beta.34", "web3": "1.0.0-beta.34",
"ipfs-api": "17.2.7" "ipfs-api": "17.2.7",
"p-iteration": "1.1.7"
}, },
"plugins": { "plugins": {
"embark-service": {} "embark-service": {}