From 28b8eff45a3d9eeccd0b922f4fdedc2e39a94647 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Mon, 23 Apr 2018 16:42:52 -0400 Subject: [PATCH 01/21] Migrating demo to react Blockchain tab complete Whisper tab complete (requires status indicator yet) --- templates/demo/app/components/blockchain.js | 96 ++++++++++ templates/demo/app/components/whisper.js | 113 ++++++++++++ templates/demo/app/dapp.js | 187 +++++--------------- templates/demo/app/index.html | 103 +---------- templates/demo/package.json | 7 +- 5 files changed, 257 insertions(+), 249 deletions(-) create mode 100644 templates/demo/app/components/blockchain.js create mode 100644 templates/demo/app/components/whisper.js diff --git a/templates/demo/app/components/blockchain.js b/templates/demo/app/components/blockchain.js new file mode 100644 index 00000000..b4b91b12 --- /dev/null +++ b/templates/demo/app/components/blockchain.js @@ -0,0 +1,96 @@ +import EmbarkJS from 'Embark/EmbarkJS'; +import SimpleStorage from 'Embark/contracts/SimpleStorage'; +import React from 'react'; +import { Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap'; + +class Blockchain extends React.Component { + + constructor(props) { + super(props); + + this.setValue = this.setValue.bind(this); + this.getValue = this.getValue.bind(this); + this.handleChange = this.handleChange.bind(this); + + this.state = { + valueSet: 10, + valueGet: "", + logs: [] + } + } + + handleChange(e){ + this.setState({valueSet: e.target.value}); + } + + setValue(e){ + e.preventDefault(); + + var value = parseInt(this.state.valueSet, 10); + + // If web3.js 1.0 is being used + if (EmbarkJS.isNewWeb3()) { + SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount}); + this._addToLog("SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount})"); + } else { + SimpleStorage.set(value); + this._addToLog("#blockchain", "SimpleStorage.set(" + value + ")"); + } + } + + getValue(e){ + e.preventDefault(); + + if (EmbarkJS.isNewWeb3()) { + SimpleStorage.methods.get().call() + .then(_value => this.setState({valueGet: _value})) + this._addToLog("SimpleStorage.methods.get(console.log)"); + } else { + SimpleStorage.get() + .then(_value => this.setState({valueGet: _value})); + this._addToLog("SimpleStorage.get()"); + } + } + + _addToLog(txt){ + this.state.logs.push(txt); + this.setState({logs: this.state.logs}); + } + + render(){ + return ( +

1. Set the value in the blockchain

+
+ + + {' '} + + Once you set the value, the transaction will need to be mined and then the value will be updated on the blockchain. + +
+ +

2. Get the current value

+
+ + current value is {this.state.valueGet} + + Click the button to get the current value. The initial value is 100. + +
+ +

3. Contract Calls

+

Javascript calls being made:

+
+ { + this.state.logs.map((item, i) =>

{item}

) + } +
+
+ ); + } + } + + export default Blockchain; \ No newline at end of file diff --git a/templates/demo/app/components/whisper.js b/templates/demo/app/components/whisper.js new file mode 100644 index 00000000..bc1795cb --- /dev/null +++ b/templates/demo/app/components/whisper.js @@ -0,0 +1,113 @@ +import EmbarkJS from 'Embark/EmbarkJS'; +import React from 'react'; +import { Alert, Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap'; + +class Whisper extends React.Component { + + constructor(props) { + super(props); + + this.sendMessage = this.sendMessage.bind(this); + this.listenToChannel = this.listenToChannel.bind(this); + + this.state = { + listenTo: '', + channel: '', + message: '', + subscribedChannels: [], + messageList: [], + logs: [] + } + } + + handleChange(e, name){ + this.state[name] = e.target.value; + this.setState(this.state); + } + + sendMessage(e){ + e.preventDefault(); + EmbarkJS.Messages.sendMessage({topic: this.state.channel, data: this.state.message}); + this._addToLog("EmbarkJS.Messages.sendMessage({topic: '" + this.state.channel + "', data: '" + this.state.message + "'})"); + } + + listenToChannel(e){ + e.preventDefault(); + + let listenTo = this.state.listenTo; + + this.state.subscribedChannels.push(`subscribed to ${listenTo} now try sending a message`); + + EmbarkJS.Messages.listenTo({topic: [listenTo]}) + .then(message => this.state.messageList.push(`channel: ${listenTo} message: ${message}`)) + + this._addToLog("EmbarkJS.Messages.listenTo({topic: ['" + this.state.channel + "']}).then(function(message) {})"); + } + + _addToLog(txt){ + this.state.logs.push(txt); + this.setState({logs: this.state.logs}); + } + + render(){ + return ( + + { + !this.state.enabled ? + + The node you are using does not support Whisper + The node uses an unsupported version of Whisper + : '' + } +

Listen To channel

+
+ + this.handleChange(e, 'listenTo')} /> + {' '} + +
+ { this.state.subscribedChannels.map((item, i) =>

{item}

) } +
+

messages received:

+
+ { this.state.messageList.map((item, i) =>

{item}

) } +
+
+
+ +

Send Message

+
+ + this.handleChange(e, 'channel')} /> + {' '} + this.handleChange(e, 'message')} /> + {' '} + + +
+ +

Javascript calls being made:

+
+

EmbarkJS.Messages.setProvider('whisper')

+ { + this.state.logs.map((item, i) =>

{item}

) + } +
+
+ ); + } +} + +export default Whisper; diff --git a/templates/demo/app/dapp.js b/templates/demo/app/dapp.js index a815d5fa..d2e70b09 100644 --- a/templates/demo/app/dapp.js +++ b/templates/demo/app/dapp.js @@ -1,161 +1,54 @@ -/*globals $, SimpleStorage, document*/ +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Tabs, Tab } from 'react-bootstrap'; -import $ from 'jquery'; -import 'bootstrap'; -import 'bootstrap/dist/css/bootstrap.min.css'; import EmbarkJS from 'Embark/EmbarkJS'; -import SimpleStorage from 'Embark/contracts/SimpleStorage'; +import Blockchain from './components/blockchain'; +import Whisper from './components/whisper'; import './dapp.css'; -var addToLog = function(id, txt) { - $(id + " .logs").append("
" + txt); -}; +class App extends React.Component { -// =========================== -// Blockchain example -// =========================== -$(document).ready(function() { + constructor(props) { + super(props); - $("#blockchain button.set").click(function() { - var value = parseInt($("#blockchain input.text").val(), 10); - - // If web3.js 1.0 is being used - if (EmbarkJS.isNewWeb3()) { - SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount}); - addToLog("#blockchain", "SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount})"); - } else { - SimpleStorage.set(value); - addToLog("#blockchain", "SimpleStorage.set(" + value + ")"); + this.state = { + whisperEnabled: false } + } - }); - - $("#blockchain button.get").click(function() { - // If web3.js 1.0 is being used - if (EmbarkJS.isNewWeb3()) { - SimpleStorage.methods.get().call(function(err, value) { - $("#blockchain .value").html(value); - }); - addToLog("#blockchain", "SimpleStorage.methods.get(console.log)"); - } else { - SimpleStorage.get().then(function(value) { - $("#blockchain .value").html(value.toNumber()); - }); - addToLog("#blockchain", "SimpleStorage.get()"); - } - }); - -}); - -// =========================== -// Storage (IPFS) example -// =========================== -$(document).ready(function() { - // automatic set if config/storage.json has "enabled": true and "provider": "ipfs" - //EmbarkJS.Storage.setProvider('ipfs',{server: 'localhost', port: '5001'}); - - $("#storage .error").hide(); - //EmbarkJS.Storage.ipfsConnection.version() - // .then(function(){ - $("#status-storage").addClass('status-online'); - $("#storage-controls").show(); - // }) - // .catch(function(err) { - // if(err){ - // console.log("IPFS Connection Error => " + err.message); - // $("#storage .error").show(); - // $("#status-storage").addClass('status-offline'); - // $("#storage-controls").hide(); - // } - // }); - - $("#storage button.setIpfsText").click(function() { - var value = $("#storage input.ipfsText").val(); - EmbarkJS.Storage.saveText(value).then(function(hash) { - $("span.textHash").html(hash); - $("input.textHash").val(hash); - addToLog("#storage", "EmbarkJS.Storage.saveText('" + value + "').then(function(hash) { })"); - }) - .catch(function(err) { - if(err){ - console.log("IPFS saveText Error => " + err.message); - } - }); - }); - - $("#storage button.loadIpfsHash").click(function() { - var value = $("#storage input.textHash").val(); - EmbarkJS.Storage.get(value).then(function(content) { - $("span.ipfsText").html(content); - addToLog("#storage", "EmbarkJS.Storage.get('" + value + "').then(function(content) { })"); - }) - .catch(function(err) { - if(err){ - console.log("IPFS get Error => " + err.message); - } - }); - }); - - $("#storage button.uploadFile").click(function() { - var input = $("#storage input[type=file]"); - EmbarkJS.Storage.uploadFile(input).then(function(hash) { - $("span.fileIpfsHash").html(hash); - $("input.fileIpfsHash").val(hash); - addToLog("#storage", "EmbarkJS.Storage.uploadFile($('input[type=file]')).then(function(hash) { })"); - }) - .catch(function(err) { - if(err){ - console.log("IPFS uploadFile Error => " + err.message); - } - }); - }); - - $("#storage button.loadIpfsFile").click(function() { - var hash = $("#storage input.fileIpfsHash").val(); - var url = EmbarkJS.Storage.getUrl(hash); - var link = '' + url + ''; - $("span.ipfsFileUrl").html(link); - $(".ipfsImage").attr('src', url); - addToLog("#storage", "EmbarkJS.Storage.getUrl('" + hash + "')"); - }); - -}); - -// =========================== -// Communication (Whisper) example -// =========================== -$(document).ready(function() { - - $("#communication .error").hide(); - $("#communication .errorVersion").hide(); - if (EmbarkJS.Messages.providerName === 'whisper') { - EmbarkJS.Messages.getWhisperVersion(function(err, version) { - if (err) { - $("#communication .error").show(); - $("#communication-controls").hide(); - $("#status-communication").addClass('status-offline'); - } else { - EmbarkJS.Messages.setProvider('whisper'); - $("#status-communication").addClass('status-online'); - } + componentDidMount(){ + // TODO Verify if whisper & swarm are available + this.setState({ + whisperEnabled: false }); } - $("#communication button.listenToChannel").click(function() { - var channel = $("#communication .listen input.channel").val(); - $("#communication #subscribeList").append("
subscribed to " + channel + " now try sending a message"); - EmbarkJS.Messages.listenTo({topic: [channel]}).then(function(message) { - $("#communication #messagesList").append("
channel: " + channel + " message: " + message); - }); - addToLog("#communication", "EmbarkJS.Messages.listenTo({topic: ['" + channel + "']}).then(function(message) {})"); - }); - $("#communication button.sendMessage").click(function() { - var channel = $("#communication .send input.channel").val(); - var message = $("#communication .send input.message").val(); - EmbarkJS.Messages.sendMessage({topic: channel, data: message}); - addToLog("#communication", "EmbarkJS.Messages.sendMessage({topic: '" + channel + "', data: '" + message + "'})"); - }); + _renderStatus(title, available){ + let className = available ? 'pull-right status-online' : 'pull-right status-offline'; + return + {title} + + ; + } -}); + render(){ + return (

Embark - Usage Example

+ + + + + + Tab 2 content + + + + + +
); + } +} + +ReactDOM.render(, document.getElementById('app')); diff --git a/templates/demo/app/index.html b/templates/demo/app/index.html index 0b17e193..55521af6 100644 --- a/templates/demo/app/index.html +++ b/templates/demo/app/index.html @@ -1,107 +1,12 @@ Embark - SimpleStorage Demo - - + + -

Embark - Usage Example

- - - -
-
-

1. Set the value in the blockchain

-
- - -

Once you set the value, the transaction will need to be mined and then the value will be updated on the blockchain.

-
- -

2. Get the current value

-
-
- current value is -
- -

Click the button to get the current value. The initial value is 100.

-
- -

3. Contract Calls

-

Javascript calls being made:

-
-
+
-
- -
- -

Save text to IPFS

-
- - -

generated Hash:

-
- -

Load text from IPFS given an hash

-
- - -

result:

-
- -

upload file to ipfs

-
- - -

generated hash:

-
- -

Get file or image from ipfs

-
- - -

file available at:

-

-
- -

Javascript calls being made:

-
-
EmbarkJS.Storage.setProvider('ipfs',{server: 'localhost', port: '5001'}) -
-
-
-
- - -
-

Listen To channel

-
- - -
-

messages received:

-

-
- -

Send Message

-
- - - -
- -

Javascript calls being made:

-
-
EmbarkJS.Messages.setProvider('whisper') -
-
-
-
- + diff --git a/templates/demo/package.json b/templates/demo/package.json index c3224ae9..c60b7143 100644 --- a/templates/demo/package.json +++ b/templates/demo/package.json @@ -9,8 +9,9 @@ "author": "", "license": "ISC", "homepage": "", - "devDependencies": { - "bootstrap": "^3.3.6", - "jquery": "^1.11.3" + "dependencies": { + "react": "^16.3.2", + "react-bootstrap": "^0.32.1", + "react-dom": "^16.3.2" } } From baffdb8f3b0ecbd299c2a854ec221dc023b0cc96 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Tue, 24 Apr 2018 16:21:33 -0400 Subject: [PATCH 02/21] Added storage section --- templates/demo/app/components/storage.js | 174 +++++++++++++++++++++++ templates/demo/app/dapp.js | 13 +- 2 files changed, 182 insertions(+), 5 deletions(-) create mode 100644 templates/demo/app/components/storage.js diff --git a/templates/demo/app/components/storage.js b/templates/demo/app/components/storage.js new file mode 100644 index 00000000..d800868b --- /dev/null +++ b/templates/demo/app/components/storage.js @@ -0,0 +1,174 @@ +import EmbarkJS from 'Embark/EmbarkJS'; +import React from 'react'; +import { Alert, Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap'; + +class Storage extends React.Component { + + constructor(props) { + super(props); + + this.state = { + textToSave: 'hello world!', + generatedHash: '', + loadText: '', + storedText: '', + fileToUpload: null, + fileHash: '', + imageToDownload: '', + url: '', + logs: [] + }; + + this.setText = this.setText.bind(this); + this.loadHash = this.loadHash.bind(this); + this.uploadFile = this.uploadFile.bind(this); + this.handleFileUpload = this.handleFileUpload.bind(this); + this.loadFile = this.loadFile.bind(this); + } + + handleChange(e, name){ + this.state[name] = e.target.value; + this.setState(this.state); + } + + handleFileUpload(e){ + this.setState({ fileToUpload: [e.target] }); + } + + _addToLog(txt){ + this.state.logs.push(txt); + this.setState({logs: this.state.logs}); + } + + setText(e){ + e.preventDefault(); + + let _this = this; + + EmbarkJS.Storage.saveText(this.state.textToSave) + .then(function(hash) { + _this.setState({ + generatedHash: hash, + loadText: hash + }); + _this._addToLog("EmbarkJS.Storage.saveText('" + _this.state.textToSave + "').then(function(hash) { })"); + }) + .catch(function(err) { + if(err){ + console.log("Storage saveText Error => " + err.message); + } + }); + } + + loadHash(e){ + e.preventDefault(); + + let _this = this; + + EmbarkJS.Storage.get(this.state.loadText) + .then(function(content) { + _this.setState({storedText: content}); + _this._addToLog("EmbarkJS.Storage.get('" + _this.state.loadText + "').then(function(content) { })"); + }) + .catch(function(err) { + if(err){ + console.log("Storage get Error => " + err.message); + } + }); + } + + uploadFile(e){ + e.preventDefault(); + + let _this = this; + + EmbarkJS.Storage.uploadFile(this.state.fileToUpload) + .then(function(hash) { + _this.setState({ + fileHash: hash, + imageToDownload: hash + }); + _this._addToLog("EmbarkJS.Storage.uploadFile(this.state.fileToUpload).then(function(hash) { })"); + }) + .catch(function(err) { + if(err){ + console.log("Storage uploadFile Error => " + err.message); + } + }); + } + + loadFile(e){ + let _url = EmbarkJS.Storage.getUrl(this.state.imageToDownload); + this.setState({url: _url}) + this._addToLog("EmbarkJS.Storage.getUrl('" + this.state.imageToDownload + "')"); + } + + render(){ + return + { + !this.props.enabled ? + + The node you are using does not support IPFS. Please ensure CORS is setup for the IPFS node. + : '' + } + +

Save text to storage

+
+ + this.handleChange(e, 'textToSave')} /> + + generated Hash: {this.state.generatedHash} + +
+ +

Load text from storage given an hash

+
+ + this.handleChange(e, 'loadText')} /> + + result: {this.state.storedText} + +
+ +

Upload file to storage

+
+ + + + generated hash: {this.state.fileHash} + +
+ +

Get file or image from storage

+
+ + this.handleChange(e, 'imageToDownload')} /> + + file available at: {this.state.url} + + +
+ +

Javascript calls being made:

+
+

EmbarkJS.Storage.setProvider('ipfs',{'{'}server: 'localhost', port: '5001'{'}'})

+ { + this.state.logs.map((item, i) =>

{item}

) + } +
+
; + } +} + +export default Storage; \ No newline at end of file diff --git a/templates/demo/app/dapp.js b/templates/demo/app/dapp.js index d2e70b09..de6b4084 100644 --- a/templates/demo/app/dapp.js +++ b/templates/demo/app/dapp.js @@ -5,6 +5,7 @@ import { Tabs, Tab } from 'react-bootstrap'; import EmbarkJS from 'Embark/EmbarkJS'; import Blockchain from './components/blockchain'; import Whisper from './components/whisper'; +import Storage from './components/storage'; import './dapp.css'; @@ -14,14 +15,16 @@ class App extends React.Component { super(props); this.state = { - whisperEnabled: false + whisperEnabled: false, + storageEnabled: false } } componentDidMount(){ - // TODO Verify if whisper & swarm are available + // TODO Verify if whisper & swarm/ipfs are available this.setState({ - whisperEnabled: false + whisperEnabled: false, + storageEnabled: false }); } @@ -40,8 +43,8 @@ class App extends React.Component { - - Tab 2 content + + From 3b13a2c80cc50da4ce662bc2376d40185b65947e Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Wed, 25 Apr 2018 20:11:15 -0400 Subject: [PATCH 03/21] Added whisper status indicator --- templates/demo/app/dapp.js | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/templates/demo/app/dapp.js b/templates/demo/app/dapp.js index de6b4084..fdc43687 100644 --- a/templates/demo/app/dapp.js +++ b/templates/demo/app/dapp.js @@ -21,10 +21,30 @@ class App extends React.Component { } componentDidMount(){ - // TODO Verify if whisper & swarm/ipfs are available + let _this = this; + + setTimeout(() => { + if (EmbarkJS.isNewWeb3()) { + EmbarkJS.Messages.Providers.whisper.getWhisperVersion(function(err, version){ + if(!err) + _this.setState({whisperEnabled: true}) + else + console.log(err); + }); + } else { + if (EmbarkJS.Messages.providerName === 'whisper') { + EmbarkJS.Messages.getWhisperVersion(function(err, version) { + if(!err) + _this.setState({whisperEnabled: true}) + else + console.log(err); + }); + } + } + }, 500); + this.setState({ - whisperEnabled: false, - storageEnabled: false + storageEnabled: true }); } From ef0bcbf405acf7f581a4f834a062b64763458fde Mon Sep 17 00:00:00 2001 From: Eric Mastro Date: Thu, 26 Apr 2018 21:37:00 +1000 Subject: [PATCH 04/21] Add 'auto' setting for geth CORS and websockets origin * 'auto' now supported for `rpcCorsDomain` and `wsOrigins` in the blockchain config. * 'auto' set to the default value in blockchain config for test and demo apps. --- lib/cmds/blockchain/geth_commands.js | 4 ++-- lib/index.js | 14 +++++++++++++- templates/boilerplate/config/blockchain.json | 4 ++-- templates/demo/config/blockchain.json | 4 ++-- test/test1/config/blockchain.json | 2 +- test_apps/contracts_app/blockchain.json | 4 ++-- test_apps/test_app/config/blockchain.json | 4 ++-- 7 files changed, 24 insertions(+), 12 deletions(-) diff --git a/lib/cmds/blockchain/geth_commands.js b/lib/cmds/blockchain/geth_commands.js index e28e559c..151b3267 100644 --- a/lib/cmds/blockchain/geth_commands.js +++ b/lib/cmds/blockchain/geth_commands.js @@ -103,14 +103,14 @@ class GethCommands { if (config.wsOrigins) { if (config.wsOrigins === '*') { console.log('=================================='); - console.log('rpcCorsDomain set to *'); + console.log('wsOrigins set to *'); console.log('make sure you know what you are doing'); console.log('=================================='); } cmd += "--wsorigins \"" + config.wsOrigins + "\" "; } else { console.log('=================================='); - console.log('warning: cors is not set'); + console.log('warning: wsOrigins is not set'); console.log('=================================='); } } diff --git a/lib/index.js b/lib/index.js index e321a4be..340d1e54 100644 --- a/lib/index.js +++ b/lib/index.js @@ -39,7 +39,19 @@ class Embark { blockchain(env, client) { this.context = [constants.contexts.blockchain]; - return require('./cmds/blockchain/blockchain.js')(this.config.blockchainConfig, client, env).run(); + let blockchainConfig = this.config.blockchainConfig; + let storageConfig = this.config.storageConfig; + let webServerConfig = this.config.webServerConfig; + + if(blockchainConfig.rpcCorsDomain === 'auto') { + if(webServerConfig) blockchainConfig.rpcCorsDomain = `http://${webServerConfig.host}:${webServerConfig.port}`; + if(storageConfig) blockchainConfig.rpcCorsDomain += `${blockchainConfig.rpcCorsDomain.length ? ',' : ''}http://${storageConfig.host}:${storageConfig.port}`; + } + if(blockchainConfig.wsOrigins === 'auto') { + if(webServerConfig) blockchainConfig.wsOrigins = `http://${webServerConfig.host}:${webServerConfig.port}`; + if(storageConfig) blockchainConfig.wsOrigins += `${blockchainConfig.wsOrigins.length ? ',' : ''}http://${storageConfig.host}:${storageConfig.port}`; + } + return require('./cmds/blockchain/blockchain.js')(blockchainConfig, client, env).run(); } simulator(options) { diff --git a/templates/boilerplate/config/blockchain.json b/templates/boilerplate/config/blockchain.json index 1d0e0820..afff2072 100644 --- a/templates/boilerplate/config/blockchain.json +++ b/templates/boilerplate/config/blockchain.json @@ -9,12 +9,12 @@ "maxpeers": 0, "rpcHost": "localhost", "rpcPort": 8545, - "rpcCorsDomain": "http://localhost:8000", + "rpcCorsDomain": "auto", "account": { "password": "config/development/password" }, "targetGasLimit": 8000000, - "wsOrigins": "http://localhost:8000", + "wsOrigins": "auto", "wsRPC": true, "wsHost": "localhost", "wsPort": 8546, diff --git a/templates/demo/config/blockchain.json b/templates/demo/config/blockchain.json index 9dccb92f..638c8167 100644 --- a/templates/demo/config/blockchain.json +++ b/templates/demo/config/blockchain.json @@ -9,12 +9,12 @@ "maxpeers": 0, "rpcHost": "localhost", "rpcPort": 8545, - "rpcCorsDomain": "http://localhost:8000", + "rpcCorsDomain": "auto", "account": { "password": "config/development/password" }, "targetGasLimit": 8000000, - "wsOrigins": "http://localhost:8000", + "wsOrigins": "auto", "wsRPC": true, "wsHost": "localhost", "wsPort": 8546, diff --git a/test/test1/config/blockchain.json b/test/test1/config/blockchain.json index 090f4078..c65ebdcd 100644 --- a/test/test1/config/blockchain.json +++ b/test/test1/config/blockchain.json @@ -7,7 +7,7 @@ "nodiscover": true, "rpcHost": "localhost", "rpcPort": 8545, - "rpcCorsDomain": "http://localhost:8000", + "rpcCorsDomain": "auto", "account": { "password": "config/development/password" } diff --git a/test_apps/contracts_app/blockchain.json b/test_apps/contracts_app/blockchain.json index 8c3790a6..35edfb43 100644 --- a/test_apps/contracts_app/blockchain.json +++ b/test_apps/contracts_app/blockchain.json @@ -9,12 +9,12 @@ "maxpeers": 0, "rpcHost": "localhost", "rpcPort": 8545, - "rpcCorsDomain": "http://localhost:8000", + "rpcCorsDomain": "auto", "account": { "password": "development/password" }, "targetGasLimit": 8000000, - "wsOrigins": "http://localhost:8000", + "wsOrigins": "auto", "wsRPC": true, "wsHost": "localhost", "wsPort": 8546 diff --git a/test_apps/test_app/config/blockchain.json b/test_apps/test_app/config/blockchain.json index 41400449..6acbdfd5 100644 --- a/test_apps/test_app/config/blockchain.json +++ b/test_apps/test_app/config/blockchain.json @@ -9,12 +9,12 @@ "maxpeers": 0, "rpcHost": "localhost", "rpcPort": 8545, - "rpcCorsDomain": "http://localhost:8000", + "rpcCorsDomain": "auto", "account": { "password": "config/development/password" }, "targetGasLimit": 8000000, - "wsOrigins": "http://localhost:8000", + "wsOrigins": "auto", "wsRPC": true, "wsHost": "localhost", "wsPort": 8546 From c818326f2e50df6a880f5a4d5d316957d817965c Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Wed, 25 Apr 2018 13:05:58 -0400 Subject: [PATCH 05/21] test add config and contract and add test --- lib/core/config.js | 2 +- .../contracts/pluginSimpleStorage.sol | 10 +++++++ .../extensions/embark-service/index.js | 22 +++++++++++----- .../test_app/test/plugin_storage_spec.js | 26 +++++++++++++++++++ 4 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 test_apps/test_app/extensions/embark-service/contracts/pluginSimpleStorage.sol create mode 100644 test_apps/test_app/test/plugin_storage_spec.js diff --git a/lib/core/config.js b/lib/core/config.js index 75e5b86f..89dd2b49 100644 --- a/lib/core/config.js +++ b/lib/core/config.js @@ -301,7 +301,7 @@ Config.prototype.loadPluginContractFiles = function() { contractsPlugins.forEach(function(plugin) { plugin.contractsFiles.forEach(function(file) { var filename = file.replace('./',''); - self.contractsFiles.push(new File({filename: filename, type: File.types.custom, resolver: function(callback) { + self.contractsFiles.push(new File({filename: filename, type: File.types.custom, path: filename, resolver: function(callback) { callback(plugin.loadPluginFile(file)); }})); }); diff --git a/test_apps/test_app/extensions/embark-service/contracts/pluginSimpleStorage.sol b/test_apps/test_app/extensions/embark-service/contracts/pluginSimpleStorage.sol new file mode 100644 index 00000000..4d01d6b3 --- /dev/null +++ b/test_apps/test_app/extensions/embark-service/contracts/pluginSimpleStorage.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.4.18; +contract PluginStorage { + address public simpleStorageAddress; + address simpleStorageAddress2; + + function PluginStorage(address addr) public { + simpleStorageAddress = addr; + } + +} diff --git a/test_apps/test_app/extensions/embark-service/index.js b/test_apps/test_app/extensions/embark-service/index.js index 0ca3ff1d..7b0d6261 100644 --- a/test_apps/test_app/extensions/embark-service/index.js +++ b/test_apps/test_app/extensions/embark-service/index.js @@ -1,12 +1,22 @@ -var Haml = require('haml'); +const Haml = require('haml'); -module.exports = function(embark) { - embark.registerServiceCheck('PluginService', function(cb) { +module.exports = function (embark) { + embark.registerServiceCheck('PluginService', function (cb) { cb({name: "ServiceName", status: "on"}); }); - embark.registerPipeline((embark.pluginConfig.files || ['**/*.haml']), function(opts) { - var source = opts.source; - return Haml.render(source); + embark.registerPipeline((embark.pluginConfig.files || ['**/*.haml']), function (opts) { + return Haml.render(opts.source); }); + + embark.registerContractConfiguration({ + "default": { + "contracts": { + "PluginStorage": { + "args": ["$SimpleStorage"] + } + } + } + }); + embark.addContractFile("./contracts/pluginSimpleStorage.sol"); }; diff --git a/test_apps/test_app/test/plugin_storage_spec.js b/test_apps/test_app/test/plugin_storage_spec.js new file mode 100644 index 00000000..24a58c4e --- /dev/null +++ b/test_apps/test_app/test/plugin_storage_spec.js @@ -0,0 +1,26 @@ +/*global contract, before, EmbarkSpec, PluginStorage, SimpleStorage, it*/ +const assert = require('assert'); + +contract("PluginSimpleStorage", function () { + this.timeout(0); + + before((done) => { + const contractsConfig = { + "SimpleStorage": { + args: [100] + }, + "PluginStorage": { + args: ["$SimpleStorage"] + } + }; + EmbarkSpec.deployAll(contractsConfig, () => { + done(); + }); + }); + + it("set SimpleStorage address", async function () { + let result = await PluginStorage.methods.simpleStorageAddress().call(); + assert.equal(result.toString(), SimpleStorage.options.address); + }); + +}); From 61be2c7bd78864ac6483975fe2ace845e700575c Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Wed, 25 Apr 2018 15:01:01 -0400 Subject: [PATCH 06/21] addFileToPipeline test and registerBeforeDeploy with new arg --- lib/contracts/deploy.js | 12 ++++++------ lib/core/config.js | 2 +- .../extensions/embark-service/fileInPipeline.js | 1 + .../test_app/extensions/embark-service/index.js | 8 ++++++++ test_apps/test_app/package.json | 2 +- 5 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 test_apps/test_app/extensions/embark-service/fileInPipeline.js diff --git a/lib/contracts/deploy.js b/lib/contracts/deploy.js index d1b87ade..f37abec4 100644 --- a/lib/contracts/deploy.js +++ b/lib/contracts/deploy.js @@ -280,17 +280,17 @@ class Deploy { // calling each beforeDeploy handler declared by the plugin async.eachSeries(plugin.beforeDeploy, (beforeDeployFn, eachCb) => { + function beforeDeployCb(resObj){ + contract.code = resObj.contractCode; + eachCb(); + } beforeDeployFn({ embarkDeploy: self, pluginConfig: plugin.pluginConfig, deploymentAccount: deploymentAccount, contract: contract, - callback: - (function(resObj){ - contract.code = resObj.contractCode; - eachCb(); - }) - }); + callback: beforeDeployCb + }, beforeDeployCb); }, () => { //self.logger.info('All beforeDeploy handlers of the plugin has processed.'); eachPluginCb(); diff --git a/lib/core/config.js b/lib/core/config.js index 89dd2b49..7061fadd 100644 --- a/lib/core/config.js +++ b/lib/core/config.js @@ -286,7 +286,7 @@ Config.prototype.loadFiles = function(files) { } }); filesFromPlugins.filter(function(file) { - if (utils.fileMatchesPattern(files, file.intendedPath)) { + if ((file.intendedPath && utils.fileMatchesPattern(files, file.intendedPath)) || utils.fileMatchesPattern(files, file.file)) { readFiles.push(file); } }); diff --git a/test_apps/test_app/extensions/embark-service/fileInPipeline.js b/test_apps/test_app/extensions/embark-service/fileInPipeline.js new file mode 100644 index 00000000..85f76853 --- /dev/null +++ b/test_apps/test_app/extensions/embark-service/fileInPipeline.js @@ -0,0 +1 @@ +console.log('File added to the pipeline using embark.addFileToPipeline'); diff --git a/test_apps/test_app/extensions/embark-service/index.js b/test_apps/test_app/extensions/embark-service/index.js index 7b0d6261..be4f4366 100644 --- a/test_apps/test_app/extensions/embark-service/index.js +++ b/test_apps/test_app/extensions/embark-service/index.js @@ -19,4 +19,12 @@ module.exports = function (embark) { } }); embark.addContractFile("./contracts/pluginSimpleStorage.sol"); + + embark.addFileToPipeline('./fileInPipeline.js'); + embark.addFileToPipeline('./fileInPipeline.js', 'js/fileInPipeline.js'); + + embark.registerBeforeDeploy(function(options, callback) { + // Just calling register to prove it works. We don't actually want to change the contracts + callback({contractCode: options.contract.code}); + }); }; diff --git a/test_apps/test_app/package.json b/test_apps/test_app/package.json index 8711dde1..80985c8d 100644 --- a/test_apps/test_app/package.json +++ b/test_apps/test_app/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "bootstrap": "^3.3.6", - "embark-service": "./extensions/embark-service", + "embark-service": "file:extensions/embark-service", "jquery": "^1.11.3", "react": "^16.0.0", "react-bootstrap": "^0.32.0", From e4566f9f817ab15156febf4130e34abff1b483fb Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Wed, 25 Apr 2018 16:27:47 -0400 Subject: [PATCH 07/21] add more registers but generation one fails in run --- lib/contracts/code_generator.js | 2 ++ .../extensions/embark-service/index.js | 27 ++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/contracts/code_generator.js b/lib/contracts/code_generator.js index 3072cd81..6b8306ae 100644 --- a/lib/contracts/code_generator.js +++ b/lib/contracts/code_generator.js @@ -19,6 +19,8 @@ const Templates = { class CodeGenerator { constructor(options) { this.blockchainConfig = options.blockchainConfig || {}; + this.rpcHost = this.blockchainConfig.rpcHost || ''; + this.rpcPort = this.blockchainConfig.rpcPort || ''; this.contractsConfig = options.contractsConfig || {}; this.storageConfig = options.storageConfig || {}; this.communicationConfig = options.communicationConfig || {}; diff --git a/test_apps/test_app/extensions/embark-service/index.js b/test_apps/test_app/extensions/embark-service/index.js index be4f4366..773c00b1 100644 --- a/test_apps/test_app/extensions/embark-service/index.js +++ b/test_apps/test_app/extensions/embark-service/index.js @@ -23,8 +23,33 @@ module.exports = function (embark) { embark.addFileToPipeline('./fileInPipeline.js'); embark.addFileToPipeline('./fileInPipeline.js', 'js/fileInPipeline.js'); - embark.registerBeforeDeploy(function(options, callback) { + embark.registerBeforeDeploy(function (options, callback) { // Just calling register to prove it works. We don't actually want to change the contracts callback({contractCode: options.contract.code}); }); + + embark.registerClientWeb3Provider(function(options) { + return "web3 = new Web3(new Web3.providers.HttpProvider('http://" + options.rpcHost + ":" + options.rpcPort + "'));"; + }); + + /*embark.registerContractsGeneration(function (options) { + const contractGenerations = []; + Object.keys(options.contracts).map(className => { + const contract = options.contracts[className]; + const abi = JSON.stringify(contract.abiDefinition); + + contractGenerations.push(`${className} = new this.web3.eth.contract('${abi}').at('${contract.deployedAddress}')`); + }); + return contractGenerations.join('\n'); + // return ''; + });*/ + + embark.registerConsoleCommand((cmd) => { + if (cmd === "hello") { + return "hello there!"; + } + // continue to embark or next plugin; + return false; + }); + }; From 18e8f5c652911bc842316b1c3cd9d787e8964b88 Mon Sep 17 00:00:00 2001 From: emizzle Date: Fri, 27 Apr 2018 00:06:15 +1000 Subject: [PATCH 08/21] Undo changes to test config. --- test/test1/config/blockchain.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test1/config/blockchain.json b/test/test1/config/blockchain.json index c65ebdcd..090f4078 100644 --- a/test/test1/config/blockchain.json +++ b/test/test1/config/blockchain.json @@ -7,7 +7,7 @@ "nodiscover": true, "rpcHost": "localhost", "rpcPort": 8545, - "rpcCorsDomain": "auto", + "rpcCorsDomain": "http://localhost:8000", "account": { "password": "config/development/password" } From d046feb83da2295e714d2991f800a1c47f64db79 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Thu, 26 Apr 2018 14:00:41 -0400 Subject: [PATCH 09/21] fix a bug where upload cmd used plugin name --- lib/index.js | 4 +++- .../test_app/extensions/embark-service/index.js | 16 ++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/lib/index.js b/lib/index.js index e321a4be..f1a2454f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -312,7 +312,9 @@ class Embark { if (cmdPlugins.length > 0) { cmdPlugin = cmdPlugins.find((pluginCmd) => { - return pluginCmd.name == platform; + return pluginCmd.uploadCmds.some(uploadCmd => { + return uploadCmd.cmd === platform; + }); }); } if (!cmdPlugin) { diff --git a/test_apps/test_app/extensions/embark-service/index.js b/test_apps/test_app/extensions/embark-service/index.js index 773c00b1..fb5a56bd 100644 --- a/test_apps/test_app/extensions/embark-service/index.js +++ b/test_apps/test_app/extensions/embark-service/index.js @@ -32,18 +32,6 @@ module.exports = function (embark) { return "web3 = new Web3(new Web3.providers.HttpProvider('http://" + options.rpcHost + ":" + options.rpcPort + "'));"; }); - /*embark.registerContractsGeneration(function (options) { - const contractGenerations = []; - Object.keys(options.contracts).map(className => { - const contract = options.contracts[className]; - const abi = JSON.stringify(contract.abiDefinition); - - contractGenerations.push(`${className} = new this.web3.eth.contract('${abi}').at('${contract.deployedAddress}')`); - }); - return contractGenerations.join('\n'); - // return ''; - });*/ - embark.registerConsoleCommand((cmd) => { if (cmd === "hello") { return "hello there!"; @@ -52,4 +40,8 @@ module.exports = function (embark) { return false; }); + embark.events.on("contractsDeployed", function() { + embark.logger.info("plugin says: your contracts have been deployed"); + }); + }; From 3b736f56a7ef9c4edb9a6c9bbabcd709b26d477b Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 26 Apr 2018 14:15:43 -0400 Subject: [PATCH 10/21] don't error if it's an empty dapp with no contracts yet --- lib/contracts/compiler.js | 4 ++++ lib/contracts/deploy.js | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/contracts/compiler.js b/lib/contracts/compiler.js index fa474e52..8699b842 100644 --- a/lib/contracts/compiler.js +++ b/lib/contracts/compiler.js @@ -10,6 +10,10 @@ class Compiler { const self = this; let available_compilers = {}; + if (contractFiles.length === 0) { + return cb(null, {}); + } + let pluginCompilers = self.plugins.getPluginsProperty('compilers', 'compilers'); pluginCompilers.forEach(function (compilerObject) { available_compilers[compilerObject.extension] = compilerObject.cb; diff --git a/lib/contracts/deploy.js b/lib/contracts/deploy.js index d1b87ade..7cfb7b16 100644 --- a/lib/contracts/deploy.js +++ b/lib/contracts/deploy.js @@ -352,8 +352,9 @@ class Deploy { deployAll(done) { let self = this; this.logger.info("deploying contracts"); + let contracts = this.contractsManager.listContracts(); - async.eachOfSeries(this.contractsManager.listContracts(), + async.eachOfSeries(contracts, function (contract, key, callback) { self.logger.trace(arguments); self.checkAndDeployContract(contract, null, callback); @@ -364,6 +365,10 @@ class Deploy { self.logger.error(err.message); self.logger.debug(err.stack); } + if (contracts.length === 0) { + self.logger.info("no contracts found"); + return done(); + } self.logger.info("finished deploying contracts"); self.logger.trace(arguments); done(err); From 797e43cedc26c6a7d3dbf717dbe5758b9abd2aa4 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Thu, 26 Apr 2018 15:09:39 -0400 Subject: [PATCH 11/21] remove duplicated entry --- test_apps/test_app/test/token_spec.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test_apps/test_app/test/token_spec.js b/test_apps/test_app/test/token_spec.js index c76728c0..88dfc1a8 100644 --- a/test_apps/test_app/test/token_spec.js +++ b/test_apps/test_app/test/token_spec.js @@ -13,8 +13,6 @@ describe("Token", function() { var contractsConfig = { "ZAMyLib": { }, - "Token": { - }, "SimpleStorage": { args: [100] }, From 5de20c6bafbe65cf73fcc6c856ec5a5721ed05d2 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Thu, 26 Apr 2018 16:35:00 -0400 Subject: [PATCH 12/21] force zepplein version for travis --- test_apps/test_app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_apps/test_app/package.json b/test_apps/test_app/package.json index 80985c8d..b29e3d6c 100644 --- a/test_apps/test_app/package.json +++ b/test_apps/test_app/package.json @@ -19,6 +19,6 @@ "react": "^16.0.0", "react-bootstrap": "^0.32.0", "react-dom": "^16.2.0", - "zeppelin-solidity": "^1.8.0" + "zeppelin-solidity": "1.8.0" } } From 1cfe46db55026f570e989d2368b146fa94f9c586 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 26 Apr 2018 17:01:11 -0400 Subject: [PATCH 13/21] intercept logs in the app itself - stopgap fix --- lib/core/engine.js | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/lib/core/engine.js b/lib/core/engine.js index da632e3f..36cc4102 100644 --- a/lib/core/engine.js +++ b/lib/core/engine.js @@ -35,6 +35,53 @@ class Engine { this.servicesMonitor.addCheck('embarkVersion', function (cb) { return cb({name: 'Embark ' + self.version, status: 'on'}); }, 0); + + if (this.interceptLogs || this.interceptLogs === undefined) { + this.doInterceptLogs(); + } + } + + doInterceptLogs() { + var self = this; + let context = {}; + context.console = console; + + let normalizeInput = function(input) { + let args = Object.values(input); + if (args.length === 0) { + return ""; + } + if (args.length === 1) { + if (Array.isArray(args[0])) { return args[0].join(','); } + return args[0] || ""; + } + return ('[' + args.map((x) => { + if (x === null) { return "null"; } + if (x === undefined) { return "undefined"; } + if (Array.isArray(x)) { return x.join(','); } + return x; + }).toString() + ']'); + }; + + context.console.log = function() { + self.logger.info(normalizeInput(arguments)); + }; + context.console.warn = function() { + self.logger.warn(normalizeInput(arguments)); + }; + context.console.info = function() { + self.logger.info(normalizeInput(arguments)); + }; + context.console.debug = function() { + // TODO: ue JSON.stringify + self.logger.debug(normalizeInput(arguments)); + }; + context.console.trace = function() { + self.logger.trace(normalizeInput(arguments)); + }; + context.console.dir = function() { + self.logger.dir(normalizeInput(arguments)); + }; } startMonitor() { From c8effb7dcb81101d4e04b8bc2c9cf041aa475db9 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Fri, 27 Apr 2018 09:04:34 -0400 Subject: [PATCH 14/21] Updated code based on code review --- templates/demo/app/components/blockchain.js | 10 +-- templates/demo/app/components/storage.js | 70 ++++++++++----------- templates/demo/app/components/whisper.js | 26 +++----- templates/demo/app/dapp.css | 4 ++ templates/demo/app/dapp.js | 2 +- 5 files changed, 51 insertions(+), 61 deletions(-) diff --git a/templates/demo/app/components/blockchain.js b/templates/demo/app/components/blockchain.js index b4b91b12..e6e3dfce 100644 --- a/templates/demo/app/components/blockchain.js +++ b/templates/demo/app/components/blockchain.js @@ -8,10 +8,6 @@ class Blockchain extends React.Component { constructor(props) { super(props); - this.setValue = this.setValue.bind(this); - this.getValue = this.getValue.bind(this); - this.handleChange = this.handleChange.bind(this); - this.state = { valueSet: 10, valueGet: "", @@ -65,9 +61,9 @@ class Blockchain extends React.Component { + onChange={(e) => this.handleChange(e)} /> {' '} - + Once you set the value, the transaction will need to be mined and then the value will be updated on the blockchain. @@ -76,7 +72,7 @@ class Blockchain extends React.Component {
current value is {this.state.valueGet} - + Click the button to get the current value. The initial value is 100.
diff --git a/templates/demo/app/components/storage.js b/templates/demo/app/components/storage.js index d800868b..f6721453 100644 --- a/templates/demo/app/components/storage.js +++ b/templates/demo/app/components/storage.js @@ -16,14 +16,9 @@ class Storage extends React.Component { fileHash: '', imageToDownload: '', url: '', - logs: [] + logs: [], + storageError: '' }; - - this.setText = this.setText.bind(this); - this.loadHash = this.loadHash.bind(this); - this.uploadFile = this.uploadFile.bind(this); - this.handleFileUpload = this.handleFileUpload.bind(this); - this.loadFile = this.loadFile.bind(this); } handleChange(e, name){ @@ -35,7 +30,7 @@ class Storage extends React.Component { this.setState({ fileToUpload: [e.target] }); } - _addToLog(txt){ + addToLog(txt){ this.state.logs.push(txt); this.setState({logs: this.state.logs}); } @@ -43,18 +38,18 @@ class Storage extends React.Component { setText(e){ e.preventDefault(); - let _this = this; - EmbarkJS.Storage.saveText(this.state.textToSave) - .then(function(hash) { - _this.setState({ + .then((hash) => { + this.setState({ generatedHash: hash, - loadText: hash + loadText: hash, + storageError: '' }); - _this._addToLog("EmbarkJS.Storage.saveText('" + _this.state.textToSave + "').then(function(hash) { })"); + this.addToLog("EmbarkJS.Storage.saveText('" + this.state.textToSave + "').then(function(hash) { })"); }) - .catch(function(err) { + .catch((err) => { if(err){ + this.setState({storageError: err.message}); console.log("Storage saveText Error => " + err.message); } }); @@ -63,15 +58,14 @@ class Storage extends React.Component { loadHash(e){ e.preventDefault(); - let _this = this; - EmbarkJS.Storage.get(this.state.loadText) - .then(function(content) { - _this.setState({storedText: content}); - _this._addToLog("EmbarkJS.Storage.get('" + _this.state.loadText + "').then(function(content) { })"); + .then((content) => { + this.setState({storedText: content, storageError: ''}); + this.addToLog("EmbarkJS.Storage.get('" + this.state.loadText + "').then(function(content) { })"); }) - .catch(function(err) { + .catch((err) => { if(err){ + this.setState({storageError: err.message}) console.log("Storage get Error => " + err.message); } }); @@ -80,18 +74,18 @@ class Storage extends React.Component { uploadFile(e){ e.preventDefault(); - let _this = this; - EmbarkJS.Storage.uploadFile(this.state.fileToUpload) - .then(function(hash) { - _this.setState({ + .then((hash) => { + this.setState({ fileHash: hash, - imageToDownload: hash + imageToDownload: hash, + storageError: '' }); - _this._addToLog("EmbarkJS.Storage.uploadFile(this.state.fileToUpload).then(function(hash) { })"); + this.addToLog("EmbarkJS.Storage.uploadFile(this.state.fileToUpload).then(function(hash) { })"); }) - .catch(function(err) { + .catch((err) => { if(err){ + this.setState({storageError: err.message}); console.log("Storage uploadFile Error => " + err.message); } }); @@ -100,7 +94,7 @@ class Storage extends React.Component { loadFile(e){ let _url = EmbarkJS.Storage.getUrl(this.state.imageToDownload); this.setState({url: _url}) - this._addToLog("EmbarkJS.Storage.getUrl('" + this.state.imageToDownload + "')"); + this.addToLog("EmbarkJS.Storage.getUrl('" + this.state.imageToDownload + "')"); } render(){ @@ -111,7 +105,11 @@ class Storage extends React.Component { The node you are using does not support IPFS. Please ensure CORS is setup for the IPFS node. : '' } - + { + this.state.storageError !== '' ? + {this.state.storageError} + : '' + }

Save text to storage

@@ -119,11 +117,11 @@ class Storage extends React.Component { type="text" defaultValue={this.state.textToSave} onChange={e => this.handleChange(e, 'textToSave')} /> - + generated Hash: {this.state.generatedHash}
- +

Load text from storage given an hash

@@ -131,7 +129,7 @@ class Storage extends React.Component { type="text" value={this.state.loadText} onChange={e => this.handleChange(e, 'loadText')} /> - + result: {this.state.storedText}
@@ -141,8 +139,8 @@ class Storage extends React.Component { - + onChange={(e) => this.handleFileUpload(e)} /> + generated hash: {this.state.fileHash} @@ -154,7 +152,7 @@ class Storage extends React.Component { type="text" value={this.state.imageToDownload} onChange={e => this.handleChange(e, 'imageToDownload')} /> - + file available at: {this.state.url} diff --git a/templates/demo/app/components/whisper.js b/templates/demo/app/components/whisper.js index bc1795cb..be78c62e 100644 --- a/templates/demo/app/components/whisper.js +++ b/templates/demo/app/components/whisper.js @@ -6,9 +6,6 @@ class Whisper extends React.Component { constructor(props) { super(props); - - this.sendMessage = this.sendMessage.bind(this); - this.listenToChannel = this.listenToChannel.bind(this); this.state = { listenTo: '', @@ -28,23 +25,21 @@ class Whisper extends React.Component { sendMessage(e){ e.preventDefault(); EmbarkJS.Messages.sendMessage({topic: this.state.channel, data: this.state.message}); - this._addToLog("EmbarkJS.Messages.sendMessage({topic: '" + this.state.channel + "', data: '" + this.state.message + "'})"); + this.addToLog("EmbarkJS.Messages.sendMessage({topic: '" + this.state.channel + "', data: '" + this.state.message + "'})"); } listenToChannel(e){ e.preventDefault(); - let listenTo = this.state.listenTo; + this.state.subscribedChannels.push(`subscribed to ${this.state.listenTo} now try sending a message`); - this.state.subscribedChannels.push(`subscribed to ${listenTo} now try sending a message`); + EmbarkJS.Messages.listenTo({topic: [this.state.listenTo]}) + .then(message => this.state.messageList.push(`channel: ${this.state.listenTo} message: ${message}`)) - EmbarkJS.Messages.listenTo({topic: [listenTo]}) - .then(message => this.state.messageList.push(`channel: ${listenTo} message: ${message}`)) - - this._addToLog("EmbarkJS.Messages.listenTo({topic: ['" + this.state.channel + "']}).then(function(message) {})"); + this.addToLog("EmbarkJS.Messages.listenTo({topic: ['" + this.state.listenTo + "']}).then(function(message) {})"); } - _addToLog(txt){ + addToLog(txt){ this.state.logs.push(txt); this.setState({logs: this.state.logs}); } @@ -53,7 +48,7 @@ class Whisper extends React.Component { return ( { - !this.state.enabled ? + !this.props.enabled ? The node you are using does not support Whisper The node uses an unsupported version of Whisper @@ -67,8 +62,7 @@ class Whisper extends React.Component { defaultValue={this.state.listenTo} placeholder="channel" onChange={e => this.handleChange(e, 'listenTo')} /> - {' '} - +
{ this.state.subscribedChannels.map((item, i) =>

{item}

) }
@@ -87,14 +81,12 @@ class Whisper extends React.Component { defaultValue={this.state.channel} placeholder="channel" onChange={e => this.handleChange(e, 'channel')} /> - {' '} this.handleChange(e, 'message')} /> - {' '} - + diff --git a/templates/demo/app/dapp.css b/templates/demo/app/dapp.css index e0043e37..3d355697 100644 --- a/templates/demo/app/dapp.css +++ b/templates/demo/app/dapp.css @@ -47,3 +47,7 @@ div { -webkit-border-radius: 10px; border-radius: 10px; } + +input.form-control { + margin-right: 5px; +} \ No newline at end of file diff --git a/templates/demo/app/dapp.js b/templates/demo/app/dapp.js index fdc43687..ddd6b0fa 100644 --- a/templates/demo/app/dapp.js +++ b/templates/demo/app/dapp.js @@ -64,7 +64,7 @@ class App extends React.Component {
- + From 4a9ff1fe9ddaaeb24a2b391e6b8dc0d068463eed Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Fri, 27 Apr 2018 09:16:29 -0400 Subject: [PATCH 15/21] check if testrpc is installed and warn if not --- lib/cmds/simulator.js | 12 +++++++++++- lib/index.js | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/cmds/simulator.js b/lib/cmds/simulator.js index 71cc1fbd..6366290d 100644 --- a/lib/cmds/simulator.js +++ b/lib/cmds/simulator.js @@ -3,11 +3,20 @@ let shelljs = require('shelljs'); class Simulator { constructor(options) { this.blockchainConfig = options.blockchainConfig; + this.logger = options.logger; } run(options) { let cmds = []; + const testrpc = shelljs.which('testrpc'); + const ganache = shelljs.which('ganache-cli'); + if (!testrpc && !ganache) { + this.logger.warn('Ganache CLI (TestRPC) is not installed on your machine'); + this.logger.info('You can install it by running: npm -g install ganache-cli'); + process.exit(); + } + cmds.push("-p " + (this.blockchainConfig.rpcPort || options.port || 8545)); cmds.push("-h " + (this.blockchainConfig.rpcHost || options.host || 'localhost')); cmds.push("-a " + (options.numAccounts || 10)); @@ -26,7 +35,8 @@ class Simulator { cmds.push("-b \"" + (simulatorBlocktime) +"\""); } - shelljs.exec('testrpc ' + cmds.join(' '), {async : true}); + const program = ganache ? 'ganache-cli' : 'testrpc'; + shelljs.exec(`${program} ${cmds.join(' ')}`, {async : true}); } } diff --git a/lib/index.js b/lib/index.js index 1f45d1d1..3390c36b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -57,7 +57,7 @@ class Embark { simulator(options) { this.context = options.context || [constants.contexts.simulator, constants.contexts.blockchain]; let Simulator = require('./cmds/simulator.js'); - let simulator = new Simulator({blockchainConfig: this.config.blockchainConfig}); + let simulator = new Simulator({blockchainConfig: this.config.blockchainConfig, logger: this.logger}); simulator.run(options); } From dbb640642bdad515eaa8ee1fb41ae4b74f7753e1 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Fri, 27 Apr 2018 11:47:35 -0400 Subject: [PATCH 16/21] Removed timeout --- templates/demo/app/dapp.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/templates/demo/app/dapp.js b/templates/demo/app/dapp.js index ddd6b0fa..5c5f121a 100644 --- a/templates/demo/app/dapp.js +++ b/templates/demo/app/dapp.js @@ -21,30 +21,28 @@ class App extends React.Component { } componentDidMount(){ - let _this = this; - - setTimeout(() => { + __embarkContext.execWhenReady(() => { if (EmbarkJS.isNewWeb3()) { - EmbarkJS.Messages.Providers.whisper.getWhisperVersion(function(err, version){ + EmbarkJS.Messages.Providers.whisper.getWhisperVersion((err, version) => { if(!err) - _this.setState({whisperEnabled: true}) + this.setState({whisperEnabled: true}) else console.log(err); }); } else { if (EmbarkJS.Messages.providerName === 'whisper') { - EmbarkJS.Messages.getWhisperVersion(function(err, version) { + EmbarkJS.Messages.getWhisperVersion((err, version) => { if(!err) - _this.setState({whisperEnabled: true}) + this.setState({whisperEnabled: true}) else console.log(err); }); } } - }, 500); - this.setState({ - storageEnabled: true + this.setState({ + storageEnabled: true + }); }); } From 57428a65c65a2e35a8e327cf2220abbcc6acb92a Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Fri, 27 Apr 2018 11:48:44 -0400 Subject: [PATCH 17/21] Removed spacer --- templates/demo/app/components/blockchain.js | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/demo/app/components/blockchain.js b/templates/demo/app/components/blockchain.js index e6e3dfce..b9e5e313 100644 --- a/templates/demo/app/components/blockchain.js +++ b/templates/demo/app/components/blockchain.js @@ -62,7 +62,6 @@ class Blockchain extends React.Component { type="text" defaultValue={this.state.valueSet} onChange={(e) => this.handleChange(e)} /> - {' '} Once you set the value, the transaction will need to be mined and then the value will be updated on the blockchain. From 2827deb41873fc83768509ae0b626ebac6f1bbfb Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Fri, 27 Apr 2018 13:50:57 -0400 Subject: [PATCH 18/21] fix on contract add --- lib/constants.json | 2 +- lib/contracts/contracts.js | 6 ++++++ lib/core/config.js | 9 +++++++-- lib/core/engine.js | 5 +++-- package-lock.json | 19 +++++++++++-------- package.json | 1 + test/contracts.js | 7 +++++-- 7 files changed, 34 insertions(+), 15 deletions(-) diff --git a/lib/constants.json b/lib/constants.json index 603e6711..d6bc7a60 100644 --- a/lib/constants.json +++ b/lib/constants.json @@ -13,6 +13,6 @@ "any": "any" }, "events": { - "contextChange": "contextChange" + "contractFilesChanged": "contractFilesChanged" } } diff --git a/lib/contracts/contracts.js b/lib/contracts/contracts.js index ae291124..2dd8e9a7 100644 --- a/lib/contracts/contracts.js +++ b/lib/contracts/contracts.js @@ -3,6 +3,7 @@ let async = require('async'); let Compiler = require('./compiler.js'); let utils = require('../utils/utils.js'); +const constants = require('../constants'); // TODO: create a contract object @@ -16,6 +17,11 @@ class ContractsManager { this.contractDependencies = {}; this.gasLimit = options.gasLimit; this.deployOnlyOnConfig = false; + this.events = options.events; + + this.events.on(constants.events.contractFilesChanged, (newContracts) => { + this.contractFiles = newContracts; + }); } build(done) { diff --git a/lib/core/config.js b/lib/core/config.js index 7061fadd..99e0e9c0 100644 --- a/lib/core/config.js +++ b/lib/core/config.js @@ -3,6 +3,7 @@ const File = require('./file.js'); const Plugins = require('./plugins.js'); const utils = require('../utils/utils.js'); const path = require('path'); +const deepEqual = require('deep-equal'); const constants = require('../constants'); var Config = function(options) { @@ -217,8 +218,12 @@ Config.prototype.loadWebServerConfigFile = function() { }; Config.prototype.loadEmbarkConfigFile = function() { - var contracts = this.embarkConfig.contracts; - this.contractsFiles = this.loadFiles(contracts); + const contracts = this.embarkConfig.contracts; + const newContractsFiles = this.loadFiles(contracts); + if (newContractsFiles.length !== this.contractFiles || deepEqual(newContractsFiles, this.contractFiles)) { + this.events.emit(constants.events.contractFilesChanged, newContractsFiles); + this.contractsFiles = newContractsFiles; + } // determine contract 'root' directories this.contractDirectories = contracts.map((dir) => { return dir.split("**")[0]; diff --git a/lib/core/engine.js b/lib/core/engine.js index 36cc4102..dbbe6aaf 100644 --- a/lib/core/engine.js +++ b/lib/core/engine.js @@ -197,7 +197,8 @@ class Engine { contractsConfig: this.config.contractsConfig, logger: this.logger, plugins: this.plugins, - gasLimit: false + gasLimit: false, + events: this.events }); this.deployManager = new DeployManager({ @@ -211,7 +212,7 @@ class Engine { onlyCompile: options.onlyCompile }); - this.events.on('file-event', function (fileType, _path) { + this.events.on('file-event', function (fileType) { // TODO: for now need to deploy on asset chanes as well // because the contractsManager config is corrupted after a deploy if (fileType === 'contract' || fileType === 'config') { diff --git a/package-lock.json b/package-lock.json index d2900817..d3d46b5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.2.tgz", "integrity": "sha512-Q3FWsbdmkQd1ib11A4XNWQvRD//5KpPoGawA8aB2DR7pWKoW9XQv3+dGxD/Z1eVFze23Okdo27ZQytVFlweKvQ==", "requires": { - "@types/node": "9.6.6" + "@types/node": "10.0.0" } }, "@types/lockfile": { @@ -32,16 +32,16 @@ "integrity": "sha512-pD6JuijPmrfi84qF3/TzGQ7zi0QIX+d7ZdetD6jUA6cp+IsCzAquXZfi5viesew+pfpOTIdAVKuh1SHA7KeKzg==" }, "@types/node": { - "version": "9.6.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.6.tgz", - "integrity": "sha512-SJe0g5cZeGNDP5sD8mIX3scb+eq8LQQZ60FXiKZHipYSeEFZ5EKml+NNMiO76F74TY4PoMWlNxF/YRY40FOvZQ==" + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.0.0.tgz", + "integrity": "sha512-kctoM36XiNZT86a7tPsUje+Q/yl+dqELjtYApi0T5eOQ90Elhu0MI10rmYk44yEP4v1jdDvtjQ9DFtpRtHf2Bw==" }, "@types/node-fetch": { "version": "1.6.9", "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-1.6.9.tgz", "integrity": "sha512-n2r6WLoY7+uuPT7pnEtKJCmPUGyJ+cbyBR8Avnu4+m1nzz7DwBVuyIvvlBzCZ/nrpC7rIgb3D6pNavL7rFEa9g==", "requires": { - "@types/node": "9.6.6" + "@types/node": "10.0.0" } }, "@types/semver": { @@ -54,7 +54,7 @@ "resolved": "https://registry.npmjs.org/@types/tar/-/tar-4.0.0.tgz", "integrity": "sha512-YybbEHNngcHlIWVCYsoj7Oo1JU9JqONuAlt1LlTH/lmL8BMhbzdFUgReY87a05rY1j8mfK47Del+TCkaLAXwLw==", "requires": { - "@types/node": "9.6.6" + "@types/node": "10.0.0" } }, "@types/url-join": { @@ -2138,6 +2138,11 @@ } } }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -6647,7 +6652,6 @@ "version": "1.0.35", "resolved": "https://registry.npmjs.org/node-webcrypto-ossl/-/node-webcrypto-ossl-1.0.35.tgz", "integrity": "sha1-FCJVeb0J9dY7CtbO4LqAD4xqBg0=", - "optional": true, "requires": { "mkdirp": "0.5.1", "nan": "2.9.2", @@ -10897,7 +10901,6 @@ "version": "0.1.19", "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-0.1.19.tgz", "integrity": "sha1-8CTjoCu8oW3tRtJpaMQlNaORJNw=", - "optional": true, "requires": { "tslib": "1.9.0" } diff --git a/package.json b/package.json index 28aa1df6..1d395214 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "colors": "^1.1.2", "commander": "^2.15.1", "css-loader": "^0.28.11", + "deep-equal": "^1.0.1", "ejs": "^2.5.8", "ethereumjs-testrpc": "^6.0.3", "file-loader": "^1.1.5", diff --git a/test/contracts.js b/test/contracts.js index 466ed101..229aa0f2 100644 --- a/test/contracts.js +++ b/test/contracts.js @@ -3,6 +3,7 @@ let ContractsManager = require('../lib/contracts/contracts.js'); let Logger = require('../lib/core/logger.js'); let File = require('../lib/core/file.js'); let TestLogger = require('../lib/tests/test_logger.js'); +let Events = require('../lib/core/events'); let assert = require('assert'); //let SolidityCompiler = require('../lib/modules/solidity'); @@ -55,7 +56,8 @@ describe('embark.Contracts', function() { } } }, - logger: new Logger({}) + logger: new Logger({}), + events: new Events() }); describe('#build', function() { @@ -146,7 +148,8 @@ describe('embark.Contracts', function() { } } }, - logger: new Logger({}) + logger: new Logger({}), + events: new Events() }); describe('#build', function() { From 94c493e854c5e98f4e8fe4a794c31cce252cd7e1 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Fri, 27 Apr 2018 15:10:24 -0400 Subject: [PATCH 19/21] redeploy with right config on config change --- lib/constants.json | 3 ++- lib/contracts/contracts.js | 7 +++++-- lib/core/config.js | 9 +++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/constants.json b/lib/constants.json index d6bc7a60..06d6a28c 100644 --- a/lib/constants.json +++ b/lib/constants.json @@ -13,6 +13,7 @@ "any": "any" }, "events": { - "contractFilesChanged": "contractFilesChanged" + "contractFilesChanged": "contractFilesChanged", + "contractConfigChanged": "contractConfigChanged" } } diff --git a/lib/contracts/contracts.js b/lib/contracts/contracts.js index 2dd8e9a7..10f56708 100644 --- a/lib/contracts/contracts.js +++ b/lib/contracts/contracts.js @@ -19,8 +19,11 @@ class ContractsManager { this.deployOnlyOnConfig = false; this.events = options.events; - this.events.on(constants.events.contractFilesChanged, (newContracts) => { - this.contractFiles = newContracts; + this.events.on(constants.events.contractFilesChanged, (newContractFiles) => { + this.contractFiles = newContractFiles; + }); + this.events.on(constants.events.contractConfigChanged, (newContracts) => { + this.contractsConfig = newContracts; }); } diff --git a/lib/core/config.js b/lib/core/config.js index 99e0e9c0..3b6333dd 100644 --- a/lib/core/config.js +++ b/lib/core/config.js @@ -142,7 +142,12 @@ Config.prototype.loadContractsConfigFile = function() { let configFilePath = this._getFileOrOject(this.configDir, 'contracts.json', 'contracts'); - this.contractsConfig = this._mergeConfig(configFilePath, configObject, this.env); + const newContractsConfig = this._mergeConfig(configFilePath, configObject, this.env); + + if (!deepEqual(newContractsConfig, this.contractsConfig)) { + this.events.emit(constants.events.contractConfigChanged, newContractsConfig); + this.contractsConfig = newContractsConfig; + } }; Config.prototype.loadExternalContractsFiles = function() { @@ -220,7 +225,7 @@ Config.prototype.loadWebServerConfigFile = function() { Config.prototype.loadEmbarkConfigFile = function() { const contracts = this.embarkConfig.contracts; const newContractsFiles = this.loadFiles(contracts); - if (newContractsFiles.length !== this.contractFiles || deepEqual(newContractsFiles, this.contractFiles)) { + if (!this.contractFiles || newContractsFiles.length !== this.contractFiles.length || !deepEqual(newContractsFiles, this.contractFiles)) { this.events.emit(constants.events.contractFilesChanged, newContractsFiles); this.contractsFiles = newContractsFiles; } From 3f3bba33c27007a33479425ac9a5459d6a45fb58 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Fri, 27 Apr 2018 15:35:12 -0400 Subject: [PATCH 20/21] fix tests --- test/config.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/config.js b/test/config.js index 75aa7957..5921bd0e 100644 --- a/test/config.js +++ b/test/config.js @@ -3,11 +3,13 @@ const Config = require('../lib/core/config.js'); const Plugins = require('../lib/core/plugins.js'); const assert = require('assert'); const TestLogger = require('../lib/tests/test_logger.js'); +const Events = require('../lib/core/events'); describe('embark.Config', function () { let config = new Config({ env: 'myenv', - configDir: './test/test1/config/' + configDir: './test/test1/config/', + events: new Events() }); config.plugins = new Plugins({plugins: {}}); config.logger = new TestLogger({}); From 0dd2938abe2b837f2dfc1ebaa21bc062698efa48 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Fri, 27 Apr 2018 16:34:13 -0400 Subject: [PATCH 21/21] reset watchers after build to make sure files remain watch --- lib/core/engine.js | 17 +- lib/pipeline/watch.js | 15 ++ package-lock.json | 379 ++++++++++++++++++++++++++++++++++++++++-- package.json | 2 +- 4 files changed, 385 insertions(+), 28 deletions(-) diff --git a/lib/core/engine.js b/lib/core/engine.js index dbbe6aaf..a39ec5e5 100644 --- a/lib/core/engine.js +++ b/lib/core/engine.js @@ -146,17 +146,11 @@ class Engine { self.currentAbi = abi; self.contractsJSON = contractsJSON; pipeline.build(abi, contractsJSON, null, function() { + self.watch.restart(); // Necessary because changing a file while it is writing can stop it from being watched self.events.emit('outputDone'); }); }); }); - // TODO: still need to redeploy contracts because the original contracts - // config is being corrupted - this.events.on('file-event', function(fileType, _path) { - if (fileType === 'asset') { - self.events.emit('asset-changed', self.contractsManager); - } - }); } codeGeneratorService(_options) { @@ -213,6 +207,11 @@ class Engine { }); this.events.on('file-event', function (fileType) { + // TODO: still need to redeploy contracts because the original contracts + // config is being corrupted + if (fileType === 'asset') { + self.events.emit('asset-changed', self.contractsManager); + } // TODO: for now need to deploy on asset chanes as well // because the contractsManager config is corrupted after a deploy if (fileType === 'contract' || fileType === 'config') { @@ -225,8 +224,8 @@ class Engine { fileWatchService(_options) { this.events.emit("status", "Watching for changes"); - let watch = new Watch({logger: this.logger, events: this.events}); - watch.start(); + this.watch = new Watch({logger: this.logger, events: this.events}); + this.watch.start(); } webServerService() { diff --git a/lib/pipeline/watch.js b/lib/pipeline/watch.js index a436b5bc..8ece7a56 100644 --- a/lib/pipeline/watch.js +++ b/lib/pipeline/watch.js @@ -9,6 +9,7 @@ class Watch { constructor(options) { this.logger = options.logger; this.events = options.events; + this.fileWatchers = []; } start() { @@ -32,6 +33,19 @@ class Watch { this.logger.info("ready to watch file changes"); } + restart() { + this.stop(); + this.start(); + } + + stop() { + this.fileWatchers.forEach(fileWatcher => { + fileWatcher.close(); + fileWatcher = null; + }); + this.fileWatchers = []; + } + watchAssets(embarkConfig, callback) { let self = this; let appConfig = embarkConfig.app; @@ -102,6 +116,7 @@ class Watch { let configWatcher = chokidar.watch(files, { ignored: /[\/\\]\./, persistent: true, ignoreInitial: true, followSymlinks: true }); + this.fileWatchers.push(configWatcher); configWatcher .on('add', path => changeCallback('add', path)) diff --git a/package-lock.json b/package-lock.json index d3d46b5b..94dbe7e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -166,12 +166,236 @@ "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" }, "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "requires": { - "micromatch": "2.3.11", + "micromatch": "3.1.10", "normalize-path": "2.1.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } } }, "argparse": { @@ -186,6 +410,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, "requires": { "arr-flatten": "1.1.0" } @@ -229,7 +454,8 @@ "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true }, "arrify": { "version": "1.0.1", @@ -1177,6 +1403,7 @@ "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, "requires": { "expand-range": "1.8.2", "preserve": "0.2.0", @@ -1455,19 +1682,110 @@ "dev": true }, "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", + "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", "requires": { - "anymatch": "1.3.2", + "anymatch": "2.0.0", "async-each": "1.0.1", + "braces": "2.3.2", "fsevents": "1.1.3", - "glob-parent": "2.0.0", + "glob-parent": "3.1.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", - "is-glob": "2.0.1", + "is-glob": "4.0.0", + "normalize-path": "2.1.1", "path-is-absolute": "1.0.1", - "readdirp": "2.1.0" + "readdirp": "2.1.0", + "upath": "1.0.4" + }, + "dependencies": { + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } } }, "chownr": { @@ -2777,6 +3095,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, "requires": { "is-posix-bracket": "0.1.1" } @@ -2785,6 +3104,7 @@ "version": "1.8.2", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, "requires": { "fill-range": "2.2.3" } @@ -2891,6 +3211,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, "requires": { "is-extglob": "1.0.0" } @@ -2982,12 +3303,14 @@ "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true }, "fill-range": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, "requires": { "is-number": "2.1.0", "isobject": "2.1.0", @@ -3116,6 +3439,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, "requires": { "for-in": "1.0.2" } @@ -4193,6 +4517,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, "requires": { "glob-parent": "2.0.0", "is-glob": "2.0.1" @@ -4207,6 +4532,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, "requires": { "is-glob": "2.0.1" } @@ -5187,12 +5513,14 @@ "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, "requires": { "is-primitive": "2.0.0" } @@ -5205,7 +5533,8 @@ "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true }, "is-finite": { "version": "1.0.2", @@ -5232,6 +5561,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, "requires": { "is-extglob": "1.0.0" } @@ -5260,6 +5590,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, "requires": { "kind-of": "3.2.2" } @@ -5331,12 +5662,14 @@ "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true }, "is-promise": { "version": "1.0.1", @@ -5401,6 +5734,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, "requires": { "isarray": "1.0.0" } @@ -6194,6 +6528,7 @@ "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, "requires": { "arr-diff": "2.0.0", "array-unique": "0.2.1", @@ -6838,6 +7173,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, "requires": { "for-own": "0.1.5", "is-extendable": "0.1.1" @@ -7136,6 +7472,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, "requires": { "glob-base": "0.3.0", "is-dotfile": "1.0.3", @@ -7850,7 +8187,8 @@ "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true }, "private": { "version": "0.1.8", @@ -8101,6 +8439,7 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "dev": true, "requires": { "is-number": "3.0.0", "kind-of": "4.0.0" @@ -8110,6 +8449,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -8118,6 +8458,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -8128,6 +8469,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -8290,6 +8632,7 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", + "dev": true, "requires": { "is-equal-shallow": "0.1.3" } diff --git a/package.json b/package.json index 1d395214..82e17d4f 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "babel-preset-es2017": "6.24.1", "babel-preset-react": "^6.24.1", "blessed": "^0.1.81", - "chokidar": "^1.6.0", + "chokidar": "^2.0.3", "colors": "^1.1.2", "commander": "^2.15.1", "css-loader": "^0.28.11",