Merge pull request #471 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

View File

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

View File

@ -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('--locale [locale]', __('language to use (default: en)'))
.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) {
i18n.setOrDetectLocale(_options.locale);
_options.env = env || 'development';

View File

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

View File

@ -78,17 +78,27 @@ Config.prototype._updateBlockchainCors = function(){
let blockchainConfig = this.blockchainConfig;
let storageConfig = this.storageConfig;
let webServerConfig = this.webServerConfig;
let cors = '';
let corsParts = [];
if(webServerConfig && webServerConfig.enabled) {
let webServerPort = webServerConfig.port ? `:${webServerConfig.port}` : '';
if(webServerConfig.host) cors = `http://${webServerConfig.host}${webServerPort}`;
if(webServerConfig.host) corsParts.push(utils.buildUrlFromConfig(webServerConfig));
}
if(storageConfig && storageConfig.enabled) {
let storagePort = storageConfig.port ? `:${storageConfig.port}` : '';
if(storageConfig.host) cors += `${cors.length ? ',' : ''}${storageConfig.protocol || 'http'}://${storageConfig.host}${storagePort}`;
// if getUrl is specified in the config, that needs to be included in cors
// 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.wsOrigins === 'auto' && cors.length) blockchainConfig.wsOrigins = cors;
};
@ -209,7 +219,7 @@ Config.prototype.loadExternalContractsFiles = 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 = {
"default": {
@ -217,11 +227,14 @@ Config.prototype.loadStorageConfigFile = function() {
"enabled": true,
"available_providers": ["ipfs", "swarm"],
"ipfs_bin": "ipfs",
"provider": "ipfs",
"protocol": "http",
"host": "localhost",
"port": 5001,
"getUrl": "http://localhost:8080/ipfs/"
"upload": {
"provider": "ipfs",
"protocol": "http",
"host": "localhost",
"port": 5001,
"getUrl": "http://localhost:8080/ipfs/"
},
"dappConnection": [{"provider": "ipfs", "host": "localhost", "port": 5001, "getUrl": "http://localhost:8080/ipfs/"}]
}
};

View File

@ -107,10 +107,9 @@ class Engine {
"fileWatcher": this.fileWatchService,
"webServer": this.webServerService,
"namingSystem": this.namingSystem,
"ipfs": this.ipfsService,
"web3": this.web3Service,
"libraryManager": this.libraryManagerService,
"swarm": this.swarmService
"storage": this.storageService
};
let service = services[serviceName];
@ -135,7 +134,6 @@ class Engine {
logger: this.logger,
plugins: this.plugins
});
this.events.on('code-generator-ready', function () {
self.events.request('code', function (abi, contractsJSON) {
pipeline.build(abi, contractsJSON, null, () => {
@ -264,20 +262,18 @@ class Engine {
});
}
ipfsService(_options) {
this.registerModule('ipfs', {
storageService(_options) {
this.registerModule('storage', {
addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor),
storageConfig: this.config.storageConfig,
webServerConfig: this.config.webServerConfig,
blockchainConfig: this.config.blockchainConfig,
host: _options.host,
port: _options.port
});
}
swarmService(_options) {
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
port: _options.port,
servicesMonitor: this.servicesMonitor,
events: this.events,
logger: this.logger,
context: this.context
});
}

View File

@ -124,23 +124,42 @@
"Blockchain node is ready": "Blockchain node is ready",
"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?",
"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 loading the content of ": "Error while loading the content of ",
"no contracts found": "no contracts found",
"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.",
"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.",
"IPFS node is offline": "IPFS node is offline",
"IPFS node detected": "IPFS node detected",
"Webserver is offline": "Webserver is offline",
"Installing packages...": "Installing packages...",
"Next steps:": "Next steps:",
"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",
"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",
"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",
"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"
}

View File

@ -1,8 +1,5 @@
let async = require('async');
const constants = require('./constants');
const _ = require('underscore');
const StorageProcessesLauncher = require('./processes/storageProcesses/storageProcessesLauncher');
// require("./utils/debug_util.js")(__filename, async);
require('colors');
@ -67,42 +64,6 @@ class Embark {
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) {
let self = this;
self.context = options.context || [constants.contexts.run, constants.contexts.build];
@ -159,11 +120,10 @@ class Embark {
engine.startService("web3");
engine.startService("pipeline");
engine.startService("deployment");
engine.startService("storage");
engine.startService("codeGenerator");
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.logger.info(__('Ethereum node detected') + '..');
engine.config.reloadConfig();
@ -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.logger.info((__("Looking for documentation? You can find it at") + " ").cyan + "http://embark.status.im/docs/".green.underline + ".".cyan);
engine.logger.info(__("Ready").underline);
@ -249,10 +195,8 @@ class Embark {
engine.startService("web3");
engine.startService("pipeline");
engine.startService("deployment", {onlyCompile: options.onlyCompile});
engine.startService("storage");
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();
},
function deploy(callback) {
@ -305,6 +249,7 @@ class Embark {
engine.startService("libraryManager");
engine.startService("pipeline");
engine.startService("deployment", {onlyCompile: true});
engine.startService("codeGenerator");
engine.events.request('deploy:contracts', function(err) {
@ -335,7 +280,6 @@ class Embark {
}
upload(options) {
const self = this;
this.context = options.context || [constants.contexts.upload, constants.contexts.build];
let engine = new Engine({
@ -351,11 +295,12 @@ class Embark {
events: options.events,
logger: options.logger,
config: options.config,
plugins: options.plugins
plugins: options.plugins,
context: this.context
});
engine.init();
let platform = engine.config.storageConfig.provider;
let platform = engine.config.storageConfig.upload.provider;
let cmdPlugin;
async.waterfall([
@ -367,35 +312,11 @@ class Embark {
engine.startService("web3");
engine.startService("pipeline");
engine.startService("deployment");
engine.startService("storage");
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();
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){
let pluginList = engine.plugins.listPlugins();
if (pluginList.length > 0) {
@ -413,8 +334,7 @@ class Embark {
});
}
if (!cmdPlugin) {
engine.logger.info(__('try "{{ipfs}}" or "{{swarm}}"', {ipfs: 'embark upload ipfs', swarm: 'embark upload swarm'}).green);
return callback({message: 'unknown platform: ' + platform});
return callback({message: __('platform "{{platform}}" is specified as the upload provider, however no plugins have registered an upload command for "{{platform}}".', {platform: platform})});
}
callback();
},

View File

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

View File

@ -1,7 +1,8 @@
let UploadIPFS = require('./upload.js');
let utils = require('../../utils/utils.js');
let fs = require('../../core/fs.js');
let IpfsApi = require('ipfs-api');
const UploadIPFS = require('./upload.js');
const utils = require('../../utils/utils.js');
const fs = require('../../core/fs.js');
const IpfsApi = require('ipfs-api');
const _ = require('underscore');
class IPFS {
@ -9,23 +10,18 @@ class IPFS {
this.logger = embark.logger;
this.events = embark.events;
this.buildDir = options.buildDir;
this.storageConfig = embark.config.storageConfig;
this.host = options.host || this.storageConfig.host;
this.port = options.port || this.storageConfig.port;
this.storageConfig = options.storageConfig;
this.host = options.host || this.storageConfig.upload.host;
this.port = options.port || this.storageConfig.upload.port;
this.protocol = options.protocol || this.storageConfig.upload.protocol;
this.addCheck = options.addCheck;
this.embark = embark;
this.commandlineDeploy();
this.setServiceCheck();
this.addIPFSToEmbarkJS();
this.addSetProvider();
this.addIpfsObjectToConsole();
}
commandlineDeploy() {
let upload_ipfs = new UploadIPFS({
buildDir: this.buildDir || 'dist/',
storageConfig: this.storageConfig,
storageConfig: this.storageConfig.upload,
configIpfsBin: this.storageConfig.ipfs_bin || "ipfs"
});
@ -40,7 +36,7 @@ class IPFS {
if (!storageConfig.enabled) {
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;
}
@ -58,7 +54,13 @@ class IPFS {
self.addCheck('IPFS', function (cb) {
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) {
self.logger.trace("Check IPFS version error: " + err);
return cb({name: "IPFS ", status: 'off'});
@ -67,18 +69,18 @@ class IPFS {
return cb({name: ("IPFS " + body.Version), status: 'on'});
}
return cb({name: "IPFS ", status: 'on'});
});
}
});
}
addIPFSToEmbarkJS() {
addProviderToEmbarkJS() {
const self = this;
// TODO: make this a shouldAdd condition
if (this.storageConfig === {}) {
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;
}
@ -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 = "";
code += "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString();
code += "\nEmbarkJS.Storage.registerProvider('ipfs', __embarkIPFS);";
@ -98,24 +109,8 @@ class IPFS {
this.embark.addCodeToEmbarkJS(code);
}
addSetProvider() {
let config = JSON.stringify({
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);
addObjectToConsole() {
let ipfs = IpfsApi(this.host, this.port);
this.events.emit("runcode:register", "ipfs", ipfs);
}

View File

@ -44,7 +44,7 @@ class IPFS {
},
function printUrls(dir_hash, callback) {
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();
}

View File

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

View File

@ -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);
}
};

View File

@ -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;

View File

@ -3,36 +3,47 @@ let __embarkSwarm = {};
const bytes = require("eth-lib/lib/bytes");
__embarkSwarm.setProvider = function (options) {
this.bzz = web3.bzz;
this.protocol = options.protocol;
this.host = options.host;
this.port = options.port;
this.connectUrl = `${options.protocol}://${options.host}:${options.port}`;
this.connectError = new Error(`Cannot connect to Swarm node on ${this.connectUrl}`);
this._getUrl = options.getUrl || `${this.connectUrl}/bzzr:/`;
let protocol = options.protocol || 'http';
let port = options.port ? `:${options.port}` : '';
this._config = options;
this._connectUrl = `${protocol}://${options.host}${port}`;
this._connectError = new Error(`Cannot connect to Swarm node on ${this._connectUrl}`);
return new Promise((resolve, reject) => {
try {
if (!this.bzz.currentProvider) {
this.bzz.setProvider(`${options.protocol}://${options.host}:${options.port}`);
if (!web3.bzz.currentProvider && !options.useOnlyGivenProvider) {
web3.bzz.setProvider(this._connectUrl);
}
else if(options.useOnlyGivenProvider && web3.bzz.givenProvider !== null){
web3.bzz.setProvider(web3.bzz.givenProvider);
}
resolve(this);
} catch (err) {
console.log(err);
reject(this.connectError);
reject(this._connectError);
}
});
};
__embarkSwarm.isAvailable = function () {
return new Promise((resolve, reject) => {
if (!this.bzz) {
// if web3 swarm object doesn't exist
if (!web3.bzz) {
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)
.catch(() => {
reject(this.connectError);
reject(this._connectError);
});
});
};
@ -41,9 +52,9 @@ __embarkSwarm.saveText = function (text) {
return new Promise((resolve, reject) => {
this.isAvailable().then((isAvailable) => {
if (!isAvailable) {
return reject(this.connectError);
return reject(this._connectError);
}
this.bzz.upload(text)
web3.bzz.upload(text)
.then(resolve)
.catch(reject);
}).catch(reject);
@ -54,9 +65,9 @@ __embarkSwarm.get = function (hash) {
return new Promise((resolve, reject) => {
this.isAvailable().then((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))))
.catch(reject);
}).catch(reject);
@ -76,9 +87,9 @@ __embarkSwarm.uploadFile = function (inputSelector) {
const fileContent = new Uint8Array(event.target.result);
this.isAvailable().then((isAvailable) => {
if (!isAvailable) {
return reject(this.connectError);
return reject(this._connectError);
}
this.bzz.upload(fileContent)
web3.bzz.upload(fileContent)
.then(resolve)
.catch(reject);
}).catch(reject);
@ -89,6 +100,6 @@ __embarkSwarm.uploadFile = function (inputSelector) {
};
__embarkSwarm.getUrl = function (hash) {
return this._getUrl + hash;
return `${this._config.getUrl || this._connectUrl + '/bzz:/'}${hash}`;
};

View File

@ -1,6 +1,8 @@
let UploadSwarm = require('./upload.js');
let utils = require('../../utils/utils.js');
let fs = require('../../core/fs.js');
const UploadSwarm = require('./upload.js');
const utils = require('../../utils/utils.js');
const fs = require('../../core/fs.js');
const Web3Bzz = require('web3-bzz');
const _ = require('underscore');
class Swarm {
@ -8,30 +10,22 @@ class Swarm {
this.logger = embark.logger;
this.events = embark.events;
this.buildDir = options.buildDir;
this.storageConfig = embark.config.storageConfig;
this.host = options.host || this.storageConfig.host;
this.port = options.port || this.storageConfig.port;
this.storageConfig = options.storageConfig;
this.addCheck = options.addCheck;
this.embark = embark;
this.bzz = options.bzz;
this.initSwarmProvider();
this.commandlineDeploy();
this.setServiceCheck();
this.addSwarmToEmbarkJS();
this.addSetProvider();
}
initSwarmProvider(){
if(!this.bzz.currentProvider) {
this.bzz.setProvider(`http://${this.host}:${this.port}`);
}
this.providerUrl = utils.buildUrl(options.protocol || options.storageConfig.upload.protocol, options.host || options.storageConfig.upload.host, options.port || options.storageConfig.upload.port);
this.getUrl = options.storageConfig.upload.getUrl || this.providerUrl + '/bzz:/';
this.bzz = new Web3Bzz(this.providerUrl);
}
commandlineDeploy() {
this.upload_swarm = new UploadSwarm({
buildDir: this.buildDir || 'dist/',
storageConfig: this.storageConfig,
getUrl: this.getUrl,
bzz: this.bzz
});
@ -47,7 +41,7 @@ class Swarm {
if (!storageConfig.enabled) {
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;
}
@ -75,38 +69,32 @@ class Swarm {
});
}
addSwarmToEmbarkJS() {
addProviderToEmbarkJS() {
let self = this;
// TODO: make this a shouldAdd condition
if (this.storageConfig === {}) {
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;
}
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 = "";
code += "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString();
code += "\nEmbarkJS.Storage.registerProvider('swarm', __embarkSwarm);";
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;

View File

@ -7,6 +7,7 @@ class Swarm {
this.buildDir = options.buildDir || 'dist/';
this.bzz = options.bzz;
this.storageConfig = options.storageConfig;
this.getUrl = options.getUrl;
}
deploy() {
@ -31,7 +32,8 @@ class Swarm {
if (!dir_hash) {
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();
}

View File

@ -8,6 +8,8 @@ class IPFSProcess extends ProcessWrapper {
constructor(_options) {
super();
this.cors = _options.cors;
this.checkIPFSVersion();
this.startIPFSDaemon();
}
@ -31,6 +33,8 @@ class IPFSProcess extends ProcessWrapper {
startIPFSDaemon() {
const self = this;
// spawn the daemon (muhaha)
this.child = child_process.spawn('ipfs', ['daemon']);
this.child.on('error', (err) => {
@ -45,7 +49,41 @@ class IPFSProcess extends ProcessWrapper {
data = data.toString();
if (!self.readyCalled && data.indexOf('Daemon is ready') > -1) {
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);
});
@ -54,6 +92,8 @@ class IPFSProcess extends ProcessWrapper {
console.error('IPFS exited with error code ' + code);
}
});
}
kill() {

View File

@ -9,8 +9,11 @@ class StorageProcessesLauncher {
this.events = options.events;
this.storageConfig = options.storageConfig;
this.webServerConfig = options.webServerConfig;
this.blockchainConfig = options.blockchainConfig;
this.processes = {};
this.cors = this.buildCors();
this.events.on('exit', () => {
Object.keys(this.processes).forEach(processName => {
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) {
this.logger.error(__(`Storage process for ${storageName} ended before the end of this process. Code: ${code}`));
}
@ -37,13 +87,13 @@ class StorageProcessesLauncher {
modulePath: filePath,
logger: self.logger,
events: self.events,
silent: true,
silent: self.logger.logLevel !== 'trace',
exitCallback: self.processExited.bind(this, storageName)
});
self.processes[storageName].send({
action: constants.blockchain.init, options: {
storageConfig: self.storageConfig,
webServerConfig: self.webServerConfig
cors: self.buildCors(storageName)
}
});

View File

@ -9,7 +9,7 @@ class SwarmProcess extends ProcessWrapper {
constructor(options) {
super();
this.storageConfig = options.storageConfig;
this.webServerConfig = options.webServerConfig;
this.cors = options.cors;
}
startSwarmDaemon() {
@ -17,16 +17,13 @@ class SwarmProcess extends ProcessWrapper {
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';
}
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 = [
`--bzzaccount=${this.storageConfig.account.address}`,
`--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.on('error', (err) => {

View File

@ -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) {
let result = shelljs.exec(cmd, options || {silent: true});
if (result.code !== 0) {
@ -199,6 +210,39 @@ function normalizeInput(input) {
}).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 = {
joinPath: joinPath,
filesMatchingPattern: filesMatchingPattern,
@ -208,6 +252,7 @@ module.exports = {
httpGet: httpGet,
httpsGet: httpsGet,
httpGetJson: httpGetJson,
httpsGetJson: httpsGetJson,
runCmd: runCmd,
cd: cd,
sed: sed,
@ -219,5 +264,7 @@ module.exports = {
getExternalContractUrl,
toChecksumAddress: toChecksumAddress,
sha3: sha3,
normalizeInput
normalizeInput,
buildUrl,
buildUrlFromConfig
};

View File

@ -23,15 +23,17 @@ class LibraryManager {
let solcVersionInConfig = this.contractsConfig.versions.solc;
let web3VersionInConfig = this.contractsConfig.versions["web3"];
let ipfsApiVersion = this.storageConfig.versions["ipfs-api"];
let pIterationVersion = this.storageConfig.versions["p-iteration"];
this.versions['solc'] = solcVersionInConfig;
this.versions['web3'] = web3VersionInConfig;
this.versions['ipfs-api'] = ipfsApiVersion;
this.versions['p-iteration'] = pIterationVersion;
Object.keys(this.versions).forEach(versionKey => {
const newVersion = this.versions[versionKey].trim();
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;
}
});

769
package-lock.json generated
View File

@ -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": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@ -1626,7 +1642,7 @@
"browserify-zlib": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
"integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
"integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=",
"requires": {
"pako": "1.0.6"
}
@ -1847,7 +1863,7 @@
"anymatch": "2.0.0",
"async-each": "1.0.1",
"braces": "2.3.2",
"fsevents": "1.2.4",
"fsevents": "1.2.3",
"glob-parent": "3.1.0",
"inherits": "2.0.3",
"is-binary-path": "1.0.1",
@ -2232,6 +2248,11 @@
"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": {
"version": "1.0.0",
"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",
"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": {
"version": "0.1.3",
"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",
"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": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@ -2743,6 +2776,12 @@
"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": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz",
@ -2781,7 +2820,7 @@
"domain-browser": {
"version": "1.2.0",
"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": {
"version": "1.0.1",
@ -2889,7 +2928,7 @@
"errno": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
"integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
"integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=",
"requires": {
"prr": "1.0.1"
}
@ -4218,465 +4257,13 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz",
"integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==",
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.3.tgz",
"integrity": "sha512-X+57O5YkDTiEQGiw8i7wYc2nQgweIekqkepI8Q3y4wVlurgBt2SuwxTeYUYMZIGpLZH3r/TsMjczCMXE5ZOt7Q==",
"optional": true,
"requires": {
"nan": "2.9.2",
"node-pre-gyp": "0.10.0"
},
"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
}
"node-pre-gyp": "0.9.1"
}
},
"fstream": {
@ -4700,6 +4287,48 @@
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
"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": {
"version": "1.0.2",
"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-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": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
@ -5484,6 +5119,15 @@
"integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==",
"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": {
"version": "1.2.0",
"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",
"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": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
@ -6097,7 +5747,7 @@
"json-loader": {
"version": "0.5.7",
"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": {
"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": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
@ -7512,7 +7173,7 @@
"node-libs-browser": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz",
"integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==",
"integrity": "sha1-X5QmPUBPbkR2fXJpAf/wVHjWAN8=",
"requires": {
"assert": "1.4.1",
"browserify-zlib": "0.2.0",
@ -7544,6 +7205,83 @@
"resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-1.3.0.tgz",
"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": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/nodeify/-/nodeify-1.0.1.tgz",
@ -7596,6 +7334,22 @@
"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": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@ -7604,6 +7358,18 @@
"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": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
@ -7814,7 +7580,7 @@
"os-locale": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
"integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
"integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=",
"requires": {
"execa": "0.7.0",
"lcid": "1.0.0",
@ -7826,6 +7592,16 @@
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"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": {
"version": "0.3.0",
"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",
"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": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz",
@ -7868,7 +7649,7 @@
"pako": {
"version": "1.0.6",
"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": {
"version": "5.1.0",
@ -8858,6 +8639,26 @@
"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": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
@ -10214,8 +10015,7 @@
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
"dev": true
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
},
"style-loader": {
"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": {
"version": "github:dignifiedquire/webcrypto-shim#190bc9ec341375df6025b17ae12ddb2428ea49c8"
},
"webpack": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz",
"integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==",
"integrity": "sha1-d9pFGx17SxF62vQaGpO1dC8k2JQ=",
"requires": {
"acorn": "5.5.3",
"acorn-dynamic-import": "2.0.2",
@ -11597,7 +11406,7 @@
"webpack-sources": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz",
"integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==",
"integrity": "sha1-oQHrrlnWUHNU1x2AE5UKOot6WlQ=",
"requires": {
"source-list-map": "2.0.0",
"source-map": "0.6.1"
@ -11606,7 +11415,7 @@
"source-map": {
"version": "0.6.1",
"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",
"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": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/window-size/-/window-size-1.1.0.tgz",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,25 +1,39 @@
{
"default": {
"enabled": true,
"available_providers": ["ipfs", "swarm"],
"ipfs_bin": "ipfs",
"provider": "ipfs",
"host": "localhost",
"port": 5001
"available_providers": ["ipfs", "swarm"],
"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": {
"enabled": true,
"provider": "swarm",
"host": "swarm-gateways.net",
"port": false,
"getUrl": "http://swarm-gateways.net/bzzr:/"
"upload": {
"provider": "swarm",
"host": "localhost",
"port": 8500,
"getUrl": "http://localhost:8500/bzzr:/"
}
},
"livenet": {
"enabled": true,
"provider": "ipfs",
"host": "ipfs.infura.io",
"protocol": "https",
"port": false,
"getUrl": "https://ipfs.infura.io/ipfs/"
"upload":{
"provider": "ipfs",
"host": "ipfs.infura.io",
"protocol": "https",
"port": false,
"getUrl": "https://ipfs.infura.io/ipfs/"
}
}
}
}

View File

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